diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml
index e08b2ade8b..a0e7f09c95 100644
--- a/testsuite/integration-arquillian/tests/base/pom.xml
+++ b/testsuite/integration-arquillian/tests/base/pom.xml
@@ -35,7 +35,10 @@
-
-
-
- -
+
+ **/migration/**/*Test.java
+
+ **/cluster/**/*Test.java
@@ -108,29 +111,4 @@
-
-
- no-account
-
-
- **/account/**/*Test.java
-
-
-
- no-client
-
-
- **/client/**/*Test.java
-
-
-
- adapters-only
-
- **/account/**/*Test.java
- **/client/**/*Test.java
- **/migration/**/*Test.java
-
-
-
-
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java
index 9289593232..e8703b450d 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java
@@ -40,9 +40,10 @@ public class AppServerTestEnricher {
String appServerQ = (annotatedClass == null ? null
: annotatedClass.getAnnotation(AppServerContainer.class).value());
- return appServerQ == null || appServerQ.isEmpty()
- ? getAuthServerQualifier() // app server == auth server
- : appServerQ;
+ return annotatedClass == null ? null // no @AppServerContainer annotation --> no adapter test
+ : (appServerQ == null || appServerQ.isEmpty() // @AppServerContainer annotation present but qualifier not set --> relative adapter test
+ ? getAuthServerQualifier() // app server == auth server
+ : appServerQ);
}
public static String getAppServerContextRoot() {
@@ -129,7 +130,7 @@ public class AppServerTestEnricher {
String jbossHomePath = appServerInfo.getProperties().get("jbossHome");
File bin = new File(jbossHomePath + "/bin");
-
+
File clientJar = new File(jbossHomePath + "/bin/client/jboss-cli-client.jar");
if (!clientJar.exists()) {
clientJar = new File(jbossHomePath + "/bin/client/jboss-client.jar"); // AS7
@@ -137,7 +138,7 @@ public class AppServerTestEnricher {
if (!clientJar.exists()) {
throw new IOException("JBoss CLI client JAR not found.");
}
-
+
String command = "java -jar " + clientJar.getAbsolutePath();
String adapterScript = "adapter-install.cli";
String samlAdapterScript = "adapter-install-saml.cli";
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
index 5000e3b482..9cbfce6e6a 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
@@ -110,7 +110,10 @@ public class AuthServerTestEnricher {
boolean authServerCluster = authServerQualifier.endsWith("-cluster");
- String authServerType = authServerQualifier.replaceAll("^auth-server-", "").replaceAll("-cluster$", "");
+ String authServerType = authServerQualifier.replaceAll("auth-server-", "").replaceAll("-cluster", "");
+
+ log.info("authServerType:" + authServerType);
+
String authServerFrontend = authServerCluster
? "auth-server-" + authServerType + "-balancer" // in cluster mode the load-balancer container serves as auth server frontend
: authServerQualifier; // single-node mode
@@ -133,7 +136,7 @@ public class AuthServerTestEnricher {
if (suiteContext.getAuthServerInfo() == null) {
throw new RuntimeException(String.format("No auth server activated. A container matching '%s' needs to be enabled in arquillian.xml.", authServerFrontend));
}
- if (authServerCluster && !suiteContext.getAuthServerBackendsInfo().isEmpty()) {
+ if (authServerCluster && suiteContext.getAuthServerBackendsInfo().isEmpty()) {
throw new RuntimeException(String.format("No cluster backend nodes activated. Containers matching '%sN' need to be enabled in arquillian.xml.", authServerBackend));
}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java
index c4bd23b45a..929c23d2b7 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java
@@ -93,9 +93,13 @@ public final class SuiteContext {
@Override
public String toString() {
+ String containers = "Auth server: " + (isAuthServerCluster() ? "\nFrontend: " : "")
+ + authServerInfo.getQualifier() + "\n";
+ for (ContainerInfo bInfo : getAuthServerBackendsInfo()) {
+ containers += "Backend: " + bInfo + "\n";
+ }
return "SUITE CONTEXT:\n"
- + "Auth server: " + authServerInfo.getQualifier() + "\n"
- +(isAuthServerCluster() ? "Auth server cluster: " + getAuthServerBackendsInfo().size() + " nodes+\n" : "");
+ + containers;
}
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/ContainersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/ContainersTest.java
deleted file mode 100644
index 27053aef54..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/ContainersTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.keycloak.testsuite;
-
-import java.util.List;
-import org.jboss.arquillian.container.test.api.ContainerController;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import org.junit.Test;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
-
-/**
- *
- * @author tkyjovsk
- */
-public class ContainersTest extends AbstractKeycloakTest {
-
- @ArquillianResource
- ContainerController controller;
-
- @Override
- public void addTestRealms(List testRealms) {
- }
-
-
- @Test
- public void testAuthServer() {
-
- log.info("AUTH SERVER should be started.");
- assertTrue(controller.isStarted(AuthServerTestEnricher.getAuthServerQualifier()));
-
- }
-
-}
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
new file mode 100644
index 0000000000..9dd6089e06
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java
@@ -0,0 +1,59 @@
+package org.keycloak.testsuite.cluster;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.jboss.arquillian.container.test.api.ContainerController;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import static org.junit.Assert.assertTrue;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.models.Constants;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.arquillian.ContainerInfo;
+import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN;
+import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+public abstract class AbstractClusterTest extends AbstractKeycloakTest {
+
+ @ArquillianResource
+ protected ContainerController controller;
+
+ protected List backendAdminClients = new ArrayList<>();
+
+ public void startBackendNodes(int count) {
+ if (count < 0 || count > 10) {
+ throw new IllegalArgumentException();
+ }
+ assertTrue(suiteContext.getAuthServerBackendsInfo().size() >= count);
+ for (int i = 0; i < count; i++) {
+
+ ContainerInfo backendNode = suiteContext.getAuthServerBackendsInfo().get(i);
+
+ controller.start(backendNode.getQualifier());
+ assertTrue(controller.isStarted(backendNode.getQualifier()));
+
+ log.info("Initializing admin client for: '" + backendNode.getContextRoot() + "/auth'");
+ backendAdminClients.add(Keycloak.getInstance(backendNode.getContextRoot() + "/auth",
+ MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID));
+ }
+ }
+
+ protected ContainerInfo backendInfo(int i) {
+ return suiteContext.getAuthServerBackendsInfo().get(i);
+ }
+
+ protected void startBackendNode(int i) {
+ String container = backendInfo(i).getQualifier();
+ if (!controller.isStarted(container)) {
+ controller.start(container);
+ }
+ }
+
+ protected void stopBackendNode(int i) {
+ controller.kill(backendInfo(i).getQualifier());
+ }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/TwoNodeClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/TwoNodeClusterTest.java
new file mode 100644
index 0000000000..0984124c0a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/TwoNodeClusterTest.java
@@ -0,0 +1,131 @@
+package org.keycloak.testsuite.cluster;
+
+import java.util.List;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.testsuite.arquillian.ContainerInfo;
+import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
+import static org.keycloak.testsuite.util.WaitUtils.pause;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+public class TwoNodeClusterTest extends AbstractClusterTest {
+
+ @Override
+ public void addTestRealms(List testRealms) {
+ }
+
+ @Before
+ public void beforeTwoNodeClusterTest() {
+ startBackendNodes(2);
+ pause(3000);
+ }
+
+ @Test
+ public void testRealm() {
+ testRealm(TEST, false);
+ }
+
+ @Test
+ public void testRealmWithFailover() {
+ testRealm(TEST + "_fo", true);
+ }
+
+ public void testRealm(String realm, boolean containerFailover) {
+ RealmRepresentation testRealm = new RealmRepresentation();
+ testRealm.setRealm(realm);
+ testRealm.setEnabled(true);
+
+ // CREATE on node1
+ log.info("Creating test realm via node1.");
+ backend1AdminClient().realms().create(testRealm);
+ log.info("Test realm created.");
+
+ // check if created on node1
+ RealmRepresentation testRealmOnBackend1 = backend1AdminClient().realms().realm(realm).toRepresentation();
+ assertEquals(testRealmOnBackend1.getRealm(), testRealm.getRealm());
+ if (containerFailover) {
+ stopBackend1();
+ }
+
+ // check if created on node2
+ RealmRepresentation testRealmOnBackend2 = backend2AdminClient().realms().realm(realm).toRepresentation();
+ assertEquals(testRealmOnBackend1.getId(), testRealmOnBackend2.getId());
+ assertEquals(testRealmOnBackend1.getRealm(), testRealmOnBackend2.getRealm());
+
+ failback();
+
+ // UPDATE on node2
+ testRealmOnBackend2.setRealm(realm + "_updated");
+ backend2AdminClient().realms().realm(realm).update(testRealmOnBackend2);
+ if (containerFailover) {
+ stopBackend2();
+ }
+ // check if updated on node1
+ testRealmOnBackend1 = backend1AdminClient().realms().realm(realm).toRepresentation();
+ assertEquals(testRealmOnBackend1.getId(), testRealmOnBackend2.getId());
+ assertEquals(testRealmOnBackend1.getRealm(), testRealmOnBackend2.getRealm());
+
+ failback();
+
+ // DELETE on node1
+ backend1AdminClient().realms().realm(realm).remove();
+ if (containerFailover) {
+ stopBackend1();
+ }
+ // check if deleted on node2
+ boolean testRealmOnBackend2Exists = false;
+ for (RealmRepresentation realmOnBackend2 : backend2AdminClient().realms().findAll()) {
+ if (realm.equals(realmOnBackend2.getRealm())
+ || testRealmOnBackend1.getId().equals(realmOnBackend2.getId())) {
+ testRealmOnBackend2Exists = true;
+ break;
+ }
+ }
+ assertFalse(testRealmOnBackend2Exists);
+ }
+
+ protected ContainerInfo backend1Info() {
+ return backendInfo(0);
+ }
+
+ protected ContainerInfo backend2Info() {
+ return backendInfo(1);
+ }
+
+ protected Keycloak backend1AdminClient() {
+ return backendAdminClients.get(0);
+ }
+
+ protected Keycloak backend2AdminClient() {
+ return backendAdminClients.get(1);
+ }
+
+ protected void startBackend1() {
+ startBackendNode(0);
+ }
+
+ protected void startBackend2() {
+ startBackendNode(1);
+ }
+
+ protected void failback() {
+ startBackend1();
+ startBackend2();
+ }
+
+ protected void stopBackend1() {
+ stopBackendNode(0);
+ }
+
+ protected void stopBackend2() {
+ stopBackendNode(1);
+ }
+
+}
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 9ad14da3a7..404f5b5fe3 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
@@ -86,11 +86,14 @@
${auth.server.wildfly.cluster}
org.jboss.as.arquillian.container.managed.ManagedDeployableContainer
${keycloak.backend1.home}
+ standalone-ha.xml
-Djboss.socket.binding.port-offset=${auth.server.backend1.port.offset}
-Xms64m -Xmx512m -XX:MaxPermSize=256m
${adapter.test.props}
+ -Djboss.node.name=node1
+
${auth.server.backend1.management.port}
${startup.timeout.sec}
@@ -100,11 +103,14 @@
${auth.server.wildfly.cluster}
org.jboss.as.arquillian.container.managed.ManagedDeployableContainer
${keycloak.backend2.home}
+ standalone-ha.xml
-Djboss.socket.binding.port-offset=${auth.server.backend2.port.offset}
-Xms64m -Xmx512m -XX:MaxPermSize=256m
${adapter.test.props}
+ -Djboss.node.name=node2
+
${auth.server.backend2.management.port}
${startup.timeout.sec}
diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml
index 715cadbe03..4e35234120 100644
--- a/testsuite/integration-arquillian/tests/pom.xml
+++ b/testsuite/integration-arquillian/tests/pom.xml
@@ -159,7 +159,27 @@
-
+
+
+ no-account
+
+ **/account/**/*Test.java
+
+
+
+ no-client
+
+ **/client/**/*Test.java
+
+
+
+ no-base
+
+ **/account/**/*Test.java
+ **/client/**/*Test.java
+
+
+
common-test-dependencies
@@ -456,12 +476,15 @@
auth-server-wildfly-cluster
+
+ -
+
auth-server-wildfly-cluster
300
1.3.173
- ${containers.home}/balancer/wildfly-${project.version}
+ ${containers.home}/balancer/wildfly-balancer-${project.version}
${containers.home}/node1/keycloak-${project.version}
${containers.home}/node2/keycloak-${project.version}
@@ -482,6 +505,8 @@
maven-surefire-plugin
+ true
+
true
false
${adapter.test.props}
@@ -495,7 +520,7 @@
102
8181
- 8181
+ 8182
8544
8545
@@ -522,19 +547,24 @@
org.keycloak.testsuite
- integration-arquillian-server-wildfly
+ integration-arquillian-server-wildfly-balancer
${project.version}
zip
- balancer
- ${containers.home}
+ ${containers.home}/balancer
org.keycloak.testsuite
integration-arquillian-server-wildfly
${project.version}
zip
- backend
- ${containers.home}
+ ${containers.home}/node1
+
+
+ org.keycloak.testsuite
+ integration-arquillian-server-wildfly
+ ${project.version}
+ zip
+ ${containers.home}/node2
true
@@ -635,6 +665,10 @@
migrated.auth.server.version
+
+
+ -
+
@@ -840,7 +874,7 @@
-
+