KEYCLOAK-5586 Add support for testing cross dc tests on jboss-based containers

This commit is contained in:
vramik 2017-09-21 15:01:01 +02:00
parent da72968085
commit f806d4a5d6
16 changed files with 779 additions and 188 deletions

View file

@ -446,19 +446,19 @@ and argument: `-p 8181`
## Cross-DC tests
Cross-DC tests use 2 data centers, each with one automatically started and one manually controlled backend servers
(currently only Keycloak on Undertow), and 1 frontend loadbalancer server node that sits in front of all servers.
Cross-DC tests use 2 data centers, each with one automatically started and one manually controlled backend servers,
and 1 frontend loadbalancer server node that sits in front of all servers.
The browser usually communicates directly with the frontent node and the test controls where the HTTP requests
land by adjusting load balancer configuration (e.g. to direct the traffic to only a single DC).
For an example of a test, see [org.keycloak.testsuite.crossdc.ActionTokenCrossDCTest](tests/base/src/test/java/org/keycloak/testsuite/crossdc/ActionTokenCrossDCTest.java).
The cross DC requires setting a profile specifying used cache server (currently only Infinispan) by specifying
`cache-server-infinispan` profile in maven.
The cross DC requires setting a profile specifying used cache server by specifying
`cache-server-infinispan` or `cache-server-jdg` profile in maven.
#### Run Cross-DC Tests from Maven
First compile the Infinispan/JDG test server via the following command:
a) First compile the Infinispan/JDG test server via the following command:
`mvn -Pcache-server-infinispan -f testsuite/integration-arquillian -DskipTests clean install`
@ -466,14 +466,30 @@ or
`mvn -Pcache-server-jdg -f testsuite/integration-arquillian -DskipTests clean install`
Then you can run the tests using the following command (adjust the test specification according to your needs):
b) Then in case you want to use **JBoss-based** containers instead of containers on Embedded Undertow run following command:
`mvn -Pcache-server-infinispan -Dtest=*.crossdc.* -pl testsuite/integration-arquillian/tests/base test`
`mvn -Pauth-servers-crossdc-jboss,auth-server-wildfly -f testsuite/integration-arquillian -DskipTests clean install`
*note: 'auth-server-wildfly' can be replaced by 'auth-server-eap'*
c1) Then you can run the tests using the following command (adjust the test specification according to your needs) for containers on **Undertow**:
`mvn -Pcache-server-infinispan,auth-servers-crossdc-undertow -Dtest=*.crossdc.* -pl testsuite/integration-arquillian/tests/base clean install`
or
`mvn -Pcache-server-jdg -Dtest=*.crossdc.* -pl testsuite/integration-arquillian/tests/base test`
`mvn -Pcache-server-jdg,auth-servers-crossdc-undertow -Dtest=*.crossdc.* -pl testsuite/integration-arquillian/tests/base clean install`
c2) For **JBoss-based** containers:
`mvn -Pcache-server-infinispan,auth-servers-crossdc-jboss,auth-server-wildfly -Dtest=*.crossdc.* -pl testsuite/integration-arquillian/tests/base clean install`
or
`mvn -Pcache-server-jdg,auth-servers-crossdc-jboss,auth-server-wildfly -Dtest=*.crossdc.* -pl testsuite/integration-arquillian/tests/base clean install`
*note: 'auth-server-wildfly can be replaced by auth-server-eap'*
It can be useful to add additional system property to enable logging:
-Dkeycloak.infinispan.logging.level=debug

View file

@ -45,7 +45,7 @@
<selenium.version>3.5.3</selenium.version>
<arquillian-drone.version>2.4.2</arquillian-drone.version>
<arquillian-graphene.version>2.3.1</arquillian-graphene.version>
<arquillian-wildfly-container.version>2.1.0.Beta1</arquillian-wildfly-container.version>
<arquillian-wildfly-container.version>2.1.0.Final</arquillian-wildfly-container.version>
<arquillian-wls-container.version>1.0.1.Final</arquillian-wls-container.version>
<arquillian-infinispan-container.version>1.2.0.Beta2</arquillian-infinispan-container.version>
<version.shrinkwrap.resolvers>2.2.6</version.shrinkwrap.resolvers>
@ -56,7 +56,7 @@
<migration.70.version>1.9.8.Final</migration.70.version>
<migration.70.authz.version>2.2.1.Final</migration.70.authz.version>
<migration.71.version>2.5.5.Final</migration.71.version>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>

View file

@ -0,0 +1,129 @@
embed-server --server-config=standalone-ha.xml
echo **** Begin ****
echo *** Update jgoups subsystem ***
/subsystem=jgroups/stack=udp/transport=UDP:write-attribute(name=site, value=${jboss.site.name})
echo *** Update infinispan subsystem ***
/subsystem=infinispan/cache-container=keycloak:write-attribute(name=module, value=org.keycloak.keycloak-model-infinispan)
echo ** Update replicated-cache work element **
/subsystem=infinispan/cache-container=keycloak/replicated-cache=work/store=custom:add( \
class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
passivation=false, \
fetch-state=false, \
purge=false, \
preload=false, \
shared=true \
)
/subsystem=infinispan/cache-container=keycloak/replicated-cache=work/store=custom:write-attribute( \
name=properties, value={ \
rawValues=true, \
marshaller=org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory, \
transportFactory=org.keycloak.models.sessions.infinispan.remotestore.KeycloakTcpTransportFactory, \
remoteServers=localhost:${remote.cache.port}, \
remoteCacheName=work, \
sessionCache=false \
} \
)
/subsystem=infinispan/cache-container=keycloak/replicated-cache=work:write-attribute(name=statistics-enabled,value=true)
echo ** Update distributed-cache sessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions/store=custom:add( \
class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
passivation=false, \
fetch-state=false, \
purge=false, \
preload=false, \
shared=true \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions/store=custom:write-attribute( \
name=properties, value={ \
remoteCacheName=sessions, \
useConfigTemplateFromCache=work, \
sessionCache=true \
} \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions:write-attribute(name=statistics-enabled,value=true)
echo ** Update distributed-cache offlineSessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions/store=custom:add( \
class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
passivation=false, \
fetch-state=false, \
purge=false, \
preload=false, \
shared=true \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions/store=custom:write-attribute( \
name=properties, value={ \
remoteCacheName=offlineSessions, \
useConfigTemplateFromCache=work, \
sessionCache=true \
} \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions:write-attribute(name=statistics-enabled,value=true)
echo ** Update distributed-cache loginFailures element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures/store=custom:add( \
class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
passivation=false, \
fetch-state=false, \
purge=false, \
preload=false, \
shared=true \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures/store=custom:write-attribute( \
name=properties, value={ \
remoteCacheName=loginFailures, \
useConfigTemplateFromCache=work, \
sessionCache=true \
} \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures:write-attribute(name=statistics-enabled,value=true)
echo ** Update distributed-cache actionTokens element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens/store=custom:add( \
class=org.keycloak.models.sessions.infinispan.remotestore.KeycloakRemoteStoreConfigurationBuilder, \
passivation=false, \
fetch-state=false, \
purge=false, \
preload=true, \
shared=true \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens/store=custom:write-attribute( \
name=properties, value={ \
remoteCacheName=actionTokens, \
useConfigTemplateFromCache=work, \
sessionCache=false \
} \
)
/subsystem=infinispan/cache-container=keycloak/distributed-cache=actionTokens:write-attribute(name=statistics-enabled,value=true)
echo ** Update distributed-cache authenticationSessions element **
/subsystem=infinispan/cache-container=keycloak/distributed-cache=authenticationSessions:write-attribute(name=statistics-enabled,value=true)
echo *** Enable debug logging ***
/subsystem=logging/logger=org.keycloak.cluster.infinispan:add(level=DEBUG)
/subsystem=logging/logger=org.keycloak.connections.infinispan:add(level=DEBUG)
/subsystem=logging/logger=org.keycloak.models.cache.infinispan:add(level=DEBUG)
/subsystem=logging/logger=org.keycloak.models.sessions.infinispan:add(level=DEBUG)
echo *** Update undertow subsystem ***
/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding,value=true)
echo **** End ****

View file

@ -26,11 +26,11 @@
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>integration-arquillian-servers-auth-server-eap</artifactId>
<name>Auth Server - JBoss - EAP</name>
<properties>
<auth.server.jboss>eap</auth.server.jboss>
<auth.server.home>${project.build.directory}/unpacked/${product.unpacked.folder.name}</auth.server.home>
@ -57,6 +57,7 @@
<goal>enforce</goal>
</goals>
<configuration>
<skip>false</skip>
<rules>
<requireProperty>
<property>product.version</property>
@ -71,5 +72,5 @@
</plugin>
</plugins>
</build>
</project>

View file

@ -191,6 +191,7 @@
<dir>${auth.server.home}/standalone/configuration</dir>
<includes>
<include>standalone.xml</include>
<include>standalone-ha.xml</include>
</includes>
<stylesheet>${common.resources}/keycloak-server-subsystem.xsl</stylesheet>
<outputDir>${auth.server.home}/standalone/configuration</outputDir>
@ -575,6 +576,119 @@
</pluginManagement>
</build>
</profile>
<profile>
<id>auth-servers-crossdc-jboss</id>
<properties>
<crossdc.jboss.jdbc.url>jdbc:h2:tcp://localhost:9092/mem:keycloak-dc-shared;DB_CLOSE_DELAY=-1</crossdc.jboss.jdbc.url>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-profile-activation</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>auth.server.jboss</property>
<message>Profile "auth-servers-crossdc-jboss" requires activation of another profile: either "auth-server-wildfly" or "auth-server-eap".</message>
<regex>(wildfly|eap)</regex>
</requireProperty>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<executions>
<execution>
<id>jpa-h2-tcp</id>
<phase>process-resources</phase>
<goals>
<goal>transform</goal>
</goals>
<configuration>
<transformationSets>
<transformationSet>
<dir>${auth.server.home}/standalone/configuration</dir>
<includes>
<include>standalone-ha.xml</include>
</includes>
<stylesheet>${common.resources}/datasource-jdbc-url.xsl</stylesheet>
<outputDir>${auth.server.home}/standalone/configuration</outputDir>
<parameters>
<parameter>
<name>pool.name</name>
<value>KeycloakDS</value>
</parameter>
<parameter>
<name>jdbc.url</name>
<value>${crossdc.jboss.jdbc.url}</value>
</parameter>
</parameters>
</transformationSet>
</transformationSets>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>crossdc-setup</id>
<phase>process-resources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${auth.server.home}/bin/jboss-cli.sh</executable>
<arguments>
<argument>--file=${common.resources}/crossdc/cross-dc-setup.cli</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>remove-temp-data-crossdc-setup</id>
<phase>process-resources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<workingDirectory>${auth.server.home}/standalone/</workingDirectory>
<executable>rm</executable>
<arguments>
<argument>-rf</argument>
<argument>data</argument>
<argument>log</argument>
<argument>tmp</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id>auth-server-cluster</id>
<properties>

View file

@ -26,9 +26,9 @@
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>integration-arquillian-servers-auth-server-wildfly</artifactId>
<name>Auth Server - JBoss - Wildfly</name>
<dependencies>
@ -38,9 +38,20 @@
<type>zip</type>
</dependency>
</dependencies>
<properties>
<auth.server.jboss>wildfly</auth.server.jboss>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -33,6 +33,7 @@
<module name="org.keycloak.keycloak-model-infinispan"/>
<module name="org.keycloak.keycloak-model-jpa"/>
<module name="org.infinispan"/>
<module name="org.infinispan.client.hotrod"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
<module name="javax.persistence.api"/>

View file

@ -94,7 +94,7 @@ public class SimpleUndertowLoadBalancer {
.build();
undertow.start();
log.infof("Loadbalancer started and ready to serve requests on http://%s:%d", host, port);
log.infof("#### Loadbalancer started and ready to serve requests on http://%s:%d ####", host, port);
} catch (Exception e) {
throw new RuntimeException(e);
}

View file

@ -135,6 +135,11 @@ public class AuthServerTestEnricher {
return managementClient;
}
public void distinguishContainersInConsoleOutput(@Observes(precedence = 5) StartContainer event) {
log.info("*****************************************************************"
+ "*****************************************************************************");
}
public void initializeSuiteContext(@Observes(precedence = 2) BeforeSuite event) {
Set<ContainerInfo> containers = containerRegistry.get().getContainers().stream()
@ -165,15 +170,16 @@ public class AuthServerTestEnricher {
}
containers.stream()
.filter(c -> c.getQualifier().startsWith(AUTH_SERVER_CONTAINER + "-cross-dc-"))
.sorted((a, b) -> a.getQualifier().compareTo(b.getQualifier()))
.forEach(c -> {
String portOffsetString = c.getArquillianContainer().getContainerConfiguration().getContainerProperties().getOrDefault("bindHttpPortOffset", "0");
String dcString = c.getArquillianContainer().getContainerConfiguration().getContainerProperties().getOrDefault("dataCenter", "0");
updateWithAuthServerInfo(c, Integer.valueOf(portOffsetString));
suiteContext.addAuthServerBackendsInfo(Integer.valueOf(dcString), c);
});
.filter(c -> c.getQualifier().startsWith("auth-server-" + System.getProperty("node.name") + "-"))
.sorted((a, b) -> a.getQualifier().compareTo(b.getQualifier()))
.forEach(c -> {
String portOffsetString = c.getArquillianContainer().getContainerConfiguration().getContainerProperties().getOrDefault("bindHttpPortOffset", "0");
updateWithAuthServerInfo(c, Integer.valueOf(portOffsetString));
String dcString = c.getArquillianContainer().getContainerConfiguration().getContainerProperties().getOrDefault("dataCenter", "0");
suiteContext.addAuthServerBackendsInfo(Integer.valueOf(dcString), c);
});
containers.stream()
.filter(c -> c.getQualifier().startsWith("cache-server-cross-dc-"))
.sorted((a, b) -> a.getQualifier().compareTo(b.getQualifier()))

View file

@ -1,23 +1,18 @@
package org.keycloak.testsuite.arquillian;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.testsuite.Retry;
import java.util.Map;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import java.io.IOException;
import java.io.NotSerializableException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXServiceURL;
import org.jboss.arquillian.container.spi.Container;
import org.jboss.arquillian.container.spi.ContainerRegistry;
import org.jboss.arquillian.test.spi.TestEnricher;
import java.io.IOException;
import java.lang.reflect.Parameter;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
@ -26,21 +21,26 @@ import javax.management.IntrospectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXServiceURL;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.jboss.arquillian.container.spi.Container;
import org.jboss.arquillian.container.spi.ContainerRegistry;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.spi.Validate;
import org.jboss.arquillian.test.spi.TestEnricher;
import org.jboss.logging.Logger;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.testsuite.Retry;
import org.keycloak.testsuite.arquillian.annotation.JmxInfinispanCacheStatistics;
import java.util.Set;
import org.keycloak.testsuite.arquillian.annotation.JmxInfinispanChannelStatistics;
import org.keycloak.testsuite.arquillian.jmx.JmxConnectorRegistry;
import org.keycloak.testsuite.arquillian.undertow.KeycloakOnUndertow;
import org.keycloak.testsuite.crossdc.DC;
import java.io.NotSerializableException;
import java.lang.management.ManagementFactory;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.jboss.arquillian.core.spi.Validate;
import org.jboss.logging.Logger;
/**
*
@ -81,8 +81,6 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
}
private InfinispanStatistics getInfinispanCacheStatistics(JmxInfinispanCacheStatistics annotation) throws MalformedObjectNameException, IOException, MalformedURLException {
MBeanServerConnection mbsc = getJmxServerConnection(annotation);
ObjectName mbeanName = new ObjectName(String.format(
"%s:type=%s,name=\"%s(%s)\",manager=\"%s\",component=%s",
annotation.domain().isEmpty() ? getDefaultDomain(annotation.dc().getDcIndex(), annotation.dcNodeIndex()) : InfinispanConnectionProvider.JMX_DOMAIN,
@ -93,7 +91,7 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
annotation.component()
));
InfinispanStatistics value = new InfinispanCacheStatisticsImpl(mbsc, mbeanName);
InfinispanStatistics value = new InfinispanCacheStatisticsImpl(getJmxServerConnection(annotation), mbeanName);
if (annotation.domain().isEmpty()) {
try {
@ -101,7 +99,7 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
} catch (RuntimeException ex) {
if (annotation.dc() != DC.UNDEFINED && annotation.dcNodeIndex() != -1
&& suiteContext.get().getAuthServerBackendsInfo(annotation.dc().getDcIndex()).get(annotation.dcNodeIndex()).isStarted()) {
LOG.warn("Could not reset statistics for " + mbeanName);
LOG.warn("Could not reset statistics for " + mbeanName + ". The reason is: \"" + ex.getMessage() + "\"");
}
}
}
@ -110,8 +108,6 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
}
private InfinispanStatistics getJGroupsChannelStatistics(JmxInfinispanChannelStatistics annotation) throws MalformedObjectNameException, IOException, MalformedURLException {
MBeanServerConnection mbsc = getJmxServerConnection(annotation);
ObjectName mbeanName = new ObjectName(String.format(
"%s:type=%s,cluster=\"%s\"",
annotation.domain().isEmpty() ? getDefaultDomain(annotation.dc().getDcIndex(), annotation.dcNodeIndex()) : InfinispanConnectionProvider.JMX_DOMAIN,
@ -119,7 +115,7 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
annotation.cluster()
));
InfinispanStatistics value = new InfinispanChannelStatisticsImpl(mbsc, mbeanName);
InfinispanStatistics value = new InfinispanChannelStatisticsImpl(getJmxServerConnection(annotation), mbeanName);
if (annotation.domain().isEmpty()) {
try {
@ -127,7 +123,7 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
} catch (RuntimeException ex) {
if (annotation.dc() != DC.UNDEFINED && annotation.dcNodeIndex() != -1
&& suiteContext.get().getAuthServerBackendsInfo(annotation.dc().getDcIndex()).get(annotation.dcNodeIndex()).isStarted()) {
LOG.warn("Could not reset statistics for " + mbeanName);
LOG.warn("Could not reset statistics for " + mbeanName + ". The reason is: \"" + ex.getMessage() + "\"");
}
}
}
@ -162,12 +158,20 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
private String getDefaultDomain(int dcIndex, int dcNodeIndex) {
if (dcIndex != -1 && dcNodeIndex != -1) {
if (Boolean.parseBoolean(System.getProperty("auth.server.jboss.crossdc"))) {
//backend-jboss-server
return "org.wildfly.clustering.infinispan";
}
//backend-undertow-server
return InfinispanConnectionProvider.JMX_DOMAIN + "-" + suiteContext.get().getAuthServerBackendsInfo(dcIndex).get(dcNodeIndex).getQualifier();
}
//cache-server
return InfinispanConnectionProvider.JMX_DOMAIN;
}
private MBeanServerConnection getJmxServerConnection(JmxInfinispanCacheStatistics annotation) throws MalformedURLException, IOException {
private Supplier<MBeanServerConnection> getJmxServerConnection(JmxInfinispanCacheStatistics annotation) throws MalformedURLException {
final String host;
final int port;
@ -175,7 +179,46 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
ContainerInfo node = suiteContext.get().getAuthServerBackendsInfo(annotation.dc().getDcIndex()).get(annotation.dcNodeIndex());
Container container = node.getArquillianContainer();
if (container.getDeployableContainer() instanceof KeycloakOnUndertow) {
return ManagementFactory.getPlatformMBeanServer();
return () -> ManagementFactory.getPlatformMBeanServer();
}
host = "localhost";
port = container.getContainerConfiguration().getContainerProperties().containsKey("managementPort")
? Integer.valueOf(container.getContainerConfiguration().getContainerProperties().get("managementPort"))
: 9990;
} else {
host = annotation.host().isEmpty()
? System.getProperty((annotation.hostProperty().isEmpty()
? "keycloak.connectionsInfinispan.remoteStoreServer"
: annotation.hostProperty()))
: annotation.host();
port = annotation.managementPort() == -1
? Integer.valueOf(System.getProperty((annotation.managementPortProperty().isEmpty()
? "cache.server.management.port"
: annotation.managementPortProperty())))
: annotation.managementPort();
}
JMXServiceURL url = new JMXServiceURL("service:jmx:remote+http://" + host + ":" + port);
return () -> {
try {
return jmxConnectorRegistry.get().getConnection(url).getMBeanServerConnection();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
};
}
private Supplier<MBeanServerConnection> getJmxServerConnection(JmxInfinispanChannelStatistics annotation) throws MalformedURLException {
final String host;
final int port;
if (annotation.dc() != DC.UNDEFINED && annotation.dcNodeIndex() != -1) {
ContainerInfo node = suiteContext.get().getAuthServerBackendsInfo(annotation.dc().getDcIndex()).get(annotation.dcNodeIndex());
Container container = node.getArquillianContainer();
if (container.getDeployableContainer() instanceof KeycloakOnUndertow) {
return () -> ManagementFactory.getPlatformMBeanServer();
}
host = "localhost";
port = container.getContainerConfiguration().getContainerProperties().containsKey("managementPort")
@ -196,79 +239,50 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
}
JMXServiceURL url = new JMXServiceURL("service:jmx:remote+http://" + host + ":" + port);
JMXConnector jmxc = jmxConnectorRegistry.get().getConnection(url);
return jmxc.getMBeanServerConnection();
}
private MBeanServerConnection getJmxServerConnection(JmxInfinispanChannelStatistics annotation) throws MalformedURLException, IOException {
final String host;
final int port;
if (annotation.dc() != DC.UNDEFINED && annotation.dcNodeIndex() != -1) {
ContainerInfo node = suiteContext.get().getAuthServerBackendsInfo(annotation.dc().getDcIndex()).get(annotation.dcNodeIndex());
Container container = node.getArquillianContainer();
if (container.getDeployableContainer() instanceof KeycloakOnUndertow) {
return ManagementFactory.getPlatformMBeanServer();
return () -> {
try {
return jmxConnectorRegistry.get().getConnection(url).getMBeanServerConnection();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
host = "localhost";
port = container.getContainerConfiguration().getContainerProperties().containsKey("managementPort")
? Integer.valueOf(container.getContainerConfiguration().getContainerProperties().get("managementPort"))
: 9990;
} else {
host = annotation.host().isEmpty()
? System.getProperty((annotation.hostProperty().isEmpty()
? "keycloak.connectionsInfinispan.remoteStoreServer"
: annotation.hostProperty()))
: annotation.host();
port = annotation.managementPort() == -1
? Integer.valueOf(System.getProperty((annotation.managementPortProperty().isEmpty()
? "cache.server.management.port"
: annotation.managementPortProperty())))
: annotation.managementPort();
}
String jmxUrl = "service:jmx:remote+http://" + host + ":" + port;
LOG.infof("JMX Service URL: %s", jmxUrl);
JMXServiceURL url = new JMXServiceURL(jmxUrl);
JMXConnector jmxc = jmxConnectorRegistry.get().getConnection(url);
return jmxc.getMBeanServerConnection();
};
}
private static abstract class CacheStatisticsImpl implements InfinispanStatistics {
protected final MBeanServerConnection mbsc;
private final Supplier<MBeanServerConnection> mbscCreateor;
private final ObjectName mbeanNameTemplate;
private ObjectName mbeanName;
public CacheStatisticsImpl(MBeanServerConnection mbsc, ObjectName mbeanNameTemplate) {
this.mbsc = mbsc;
public CacheStatisticsImpl(Supplier<MBeanServerConnection> mbscCreateor, ObjectName mbeanNameTemplate) {
this.mbscCreateor = mbscCreateor;
this.mbeanNameTemplate = mbeanNameTemplate;
}
protected MBeanServerConnection getConnection() {
return mbscCreateor.get();
}
@Override
public boolean exists() {
try {
getMbeanName();
return true;
} catch (Exception ex) {
} catch (IOException | RuntimeException ex) {
return false;
}
}
@Override
public Map<String, Object> getStatistics() {
try {
MBeanInfo mBeanInfo = mbsc.getMBeanInfo(getMbeanName());
MBeanInfo mBeanInfo = getConnection().getMBeanInfo(getMbeanName());
String[] statAttrs = Arrays.asList(mBeanInfo.getAttributes()).stream()
.filter(MBeanAttributeInfo::isReadable)
.map(MBeanAttributeInfo::getName)
.collect(Collectors.toList())
.toArray(new String[] {});
return mbsc.getAttributes(getMbeanName(), statAttrs)
return getConnection().getAttributes(getMbeanName(), statAttrs)
.asList()
.stream()
.collect(Collectors.toMap(Attribute::getName, Attribute::getValue));
@ -279,7 +293,7 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
protected ObjectName getMbeanName() throws IOException, RuntimeException {
if (this.mbeanName == null) {
Set<ObjectName> queryNames = mbsc.queryNames(mbeanNameTemplate, null);
Set<ObjectName> queryNames = getConnection().queryNames(mbeanNameTemplate, null);
if (queryNames.isEmpty()) {
throw new RuntimeException("No MBean of template " + mbeanNameTemplate + " found at JMX server");
}
@ -292,7 +306,7 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
@Override
public Comparable getSingleStatistics(String statisticsName) {
try {
return (Comparable) mbsc.getAttribute(getMbeanName(), statisticsName);
return (Comparable) getConnection().getAttribute(getMbeanName(), statisticsName);
} catch (IOException | InstanceNotFoundException | MBeanException | ReflectionException | AttributeNotFoundException ex) {
throw new RuntimeException(ex);
}
@ -305,7 +319,7 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
try {
getMbeanName();
if (! isAvailable()) throw new RuntimeException("Not available");
} catch (Exception ex) {
} catch (IOException | RuntimeException ex) {
throw new RuntimeException("Timed out while waiting for " + mbeanNameTemplate + " to become available", ex);
}
}, 1 + (int) timeInMillis / 100, 100);
@ -316,14 +330,14 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
private static class InfinispanCacheStatisticsImpl extends CacheStatisticsImpl {
public InfinispanCacheStatisticsImpl(MBeanServerConnection mbsc, ObjectName mbeanName) {
super(mbsc, mbeanName);
public InfinispanCacheStatisticsImpl(Supplier<MBeanServerConnection> mbscCreator, ObjectName mbeanName) {
super(mbscCreator, mbeanName);
}
@Override
public void reset() {
try {
mbsc.invoke(getMbeanName(), "resetStatistics", new Object[] {}, new String[] {});
getConnection().invoke(getMbeanName(), "resetStatistics", new Object[] {}, new String[] {});
} catch (IOException | InstanceNotFoundException | MBeanException | ReflectionException ex) {
throw new RuntimeException(ex);
}
@ -337,14 +351,14 @@ public class CacheStatisticsControllerEnricher implements TestEnricher {
private static class InfinispanChannelStatisticsImpl extends CacheStatisticsImpl {
public InfinispanChannelStatisticsImpl(MBeanServerConnection mbsc, ObjectName mbeanName) {
super(mbsc, mbeanName);
public InfinispanChannelStatisticsImpl(Supplier<MBeanServerConnection> mbscCreator, ObjectName mbeanName) {
super(mbscCreator, mbeanName);
}
@Override
public void reset() {
try {
mbsc.invoke(getMbeanName(), "resetStats", new Object[] {}, new String[] {});
getConnection().invoke(getMbeanName(), "resetStats", new Object[] {}, new String[] {});
} catch (NotSerializableException ex) {
// Ignore return value not serializable, the invocation has already done its job
} catch (IOException | InstanceNotFoundException | MBeanException | ReflectionException ex) {

View file

@ -27,6 +27,7 @@ import org.jboss.arquillian.core.api.annotation.ApplicationScoped;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.test.spi.event.suite.BeforeSuite;
import org.jboss.logging.Logger;
/**
*
@ -34,6 +35,8 @@ import org.jboss.arquillian.test.spi.event.suite.BeforeSuite;
*/
public class JmxConnectorRegistryCreator {
private final Logger log = Logger.getLogger(JmxConnectorRegistryCreator.class);
@Inject
@ApplicationScoped
private InstanceProducer<JmxConnectorRegistry> connectorRegistry;
@ -46,6 +49,7 @@ public class JmxConnectorRegistryCreator {
@Override
public JMXConnector getConnection(JMXServiceURL url) {
JMXConnector res = connectors.get(url);
if (res == null) {
try {
@ -55,7 +59,10 @@ public class JmxConnectorRegistryCreator {
res = conn;
}
res.connect();
log.infof("Connected to JMX Service URL: %s", url);
} catch (IOException ex) {
//remove conn from connectors in case something goes wrong. The connection will be established on-demand
connectors.remove(url, res);
throw new RuntimeException("Could not instantiate JMX connector for " + url, ex);
}
}

View file

@ -21,8 +21,8 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.Response;
@ -58,10 +58,12 @@ import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.BasicCookieStore;
import org.hamcrest.Matchers;
import static org.hamcrest.Matchers.containsString;
/**
@ -126,8 +128,7 @@ public class ConcurrentLoginTest extends AbstractConcurrencyTest {
CookieStore cookieStore = new BasicCookieStore();
context.setCookieStore(cookieStore);
HttpUriRequest request = handleLogin(getPageContent(oauth.getLoginFormUrl(), httpClient, context), userName, password);
log.debug("Executing login request");
Assert.assertTrue(parseAndCloseResponse(httpClient.execute(request, context)).contains("<title>AUTH_RESPONSE</title>"));
Assert.assertThat(parseAndCloseResponse(httpClient.execute(request, context)), containsString("<title>AUTH_RESPONSE</title>"));
return context;
}
@ -306,12 +307,8 @@ public class ConcurrentLoginTest extends AbstractConcurrencyTest {
}
private static Map<String, String> getQueryFromUrl(String url) throws URISyntaxException {
Map<String, String> m = new HashMap<>();
List<NameValuePair> pairs = URLEncodedUtils.parse(new URI(url), "UTF-8");
for (NameValuePair p : pairs) {
m.put(p.getName(), p.getValue());
}
return m;
return URLEncodedUtils.parse(new URI(url), Charset.forName("UTF-8")).stream()
.collect(Collectors.toMap(p -> p.getName(), p -> p.getValue()));
}
@ -411,4 +408,4 @@ public class ConcurrentLoginTest extends AbstractConcurrencyTest {
}
}
}

View file

@ -50,6 +50,8 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
// Keep the following constants in sync with arquillian
public static final String QUALIFIER_NODE_BALANCER = "auth-server-balancer-cross-dc";
public static final String QUALIFIER_JBOSS_DC_0_NODE_1 = "auth-server-jboss-cross-dc-0_1";
public static final String QUALIFIER_JBOSS_DC_1_NODE_1 = "auth-server-jboss-cross-dc-1_1";
@ArquillianResource
@LoadBalancer(value = QUALIFIER_NODE_BALANCER)
@ -208,7 +210,7 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
/**
* Disables routing requests to the given data center in the load balancer.
* @param dcIndex
* @param dc
*/
public void disableDcOnLoadBalancer(DC dc) {
int dcIndex = dc.ordinal();
@ -218,7 +220,7 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
/**
* Enables routing requests to all started nodes to the given data center in the load balancer.
* @param dcIndex
* @param dc
*/
public void enableDcOnLoadBalancer(DC dc) {
int dcIndex = dc.ordinal();
@ -235,7 +237,7 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
/**
* Disables routing requests to the given node within the given data center in the load balancer.
* @param dcIndex
* @param dc
* @param nodeIndex
*/
public void disableLoadBalancerNode(DC dc, int nodeIndex) {
@ -246,7 +248,7 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
/**
* Enables routing requests to the given node within the given data center in the load balancer.
* @param dcIndex
* @param dc
* @param nodeIndex
*/
public void enableLoadBalancerNode(DC dc, int nodeIndex) {
@ -264,7 +266,7 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
/**
* Starts a manually-controlled backend auth-server node in cross-DC scenario.
* @param dcIndex
* @param dc
* @param nodeIndex
* @return Started instance descriptor.
*/
@ -275,6 +277,8 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
assertThat((Integer) nodeIndex, lessThan(dcNodes.size()));
ContainerInfo dcNode = dcNodes.get(nodeIndex);
assertTrue("Node " + dcNode.getQualifier() + " has to be controlled manually", dcNode.isManual());
log.infof("Starting backend node: %s (dcIndex: %d, nodeIndex: %d)", dcNode.getQualifier(), dcIndex, nodeIndex);
containerController.start(dcNode.getQualifier());
createRESTClientsForNode(dcNode);
@ -284,7 +288,7 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
/**
* Stops a manually-controlled backend auth-server node in cross-DC scenario.
* @param dcIndex
* @param dc
* @param nodeIndex
* @return Stopped instance descriptor.
*/
@ -298,13 +302,15 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
removeRESTClientsForNode(dcNode);
assertTrue("Node " + dcNode.getQualifier() + " has to be controlled manually", dcNode.isManual());
log.infof("Stopping backend node: %s (dcIndex: %d, nodeIndex: %d)", dcNode.getQualifier(), dcIndex, nodeIndex);
containerController.stop(dcNode.getQualifier());
return dcNode;
}
/**
* Returns stream of all nodes in the given dc that are started manually.
* @param dcIndex
* @param dc
* @return
*/
public Stream<ContainerInfo> getManuallyStartedBackendNodes(DC dc) {
@ -315,7 +321,7 @@ public abstract class AbstractCrossDCTest extends AbstractTestRealmKeycloakTest
/**
* Returns stream of all nodes in the given dc that are started automatically.
* @param dcIndex
* @param dc
* @return
*/
public Stream<ContainerInfo> getAutomaticallyStartedBackendNodes(DC dc) {

View file

@ -21,6 +21,9 @@ import java.io.IOException;
import java.net.URISyntaxException;
import javax.ws.rs.NotFoundException;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.TargetsContainer;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Before;
import org.junit.Test;
@ -31,9 +34,11 @@ import org.keycloak.models.UserLoginFailureModel;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.Retry;
import org.keycloak.testsuite.client.KeycloakTestingClient;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import org.keycloak.testsuite.util.ClientBuilder;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.RealmBuilder;
@ -45,7 +50,31 @@ import org.keycloak.testsuite.util.UserBuilder;
public class BruteForceCrossDCTest extends AbstractAdminCrossDCTest {
private static final String REALM_NAME = "brute-force-test";
@Deployment(name = "dc0")
@TargetsContainer(QUALIFIER_JBOSS_DC_0_NODE_1)
public static WebArchive deployDC0() {
return RunOnServerDeployment.create(
BruteForceCrossDCTest.class,
AbstractAdminCrossDCTest.class,
AbstractCrossDCTest.class,
AbstractTestRealmKeycloakTest.class,
KeycloakTestingClient.class
);
}
@Deployment(name = "dc1")
@TargetsContainer(QUALIFIER_JBOSS_DC_1_NODE_1)
public static WebArchive deployDC1() {
return RunOnServerDeployment.create(
BruteForceCrossDCTest.class,
AbstractAdminCrossDCTest.class,
AbstractCrossDCTest.class,
AbstractTestRealmKeycloakTest.class,
KeycloakTestingClient.class
);
}
@Before
public void beforeTest() {
try {
@ -220,6 +249,7 @@ public class BruteForceCrossDCTest extends AbstractAdminCrossDCTest {
// TODO Having this working on Wildfly might be a challenge. Maybe require @Deployment with @TargetsContainer descriptor generated at runtime as we don't know the container qualifier at compile time... Maybe workaround by add endpoint to TestingResourceProvider if needed..
// resolution on Wildfly: make deployment available on both dc0_1 and dc1_1, see @Deployment methods
private void addUserLoginFailure(KeycloakTestingClient testingClient) throws URISyntaxException, IOException {
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealmByName(REALM_NAME);

View file

@ -64,7 +64,7 @@
<container qualifier="auth-server-undertow" mode="suite" >
<configuration>
<property name="enabled">${auth.server.undertow} &amp;&amp; ! ${auth.server.undertow.crossdc}</property>
<property name="enabled">${auth.server.undertow} &amp;&amp; ! ${auth.server.crossdc}</property>
<property name="bindAddress">0.0.0.0</property>
<property name="adapterImplClass">org.keycloak.testsuite.arquillian.undertow.KeycloakOnUndertow</property>
<property name="bindHttpPort">${auth.server.http.port}</property>
@ -74,7 +74,7 @@
<container qualifier="auth-server-${auth.server}" mode="suite" >
<configuration>
<property name="enabled">${auth.server.jboss}</property>
<property name="enabled">${auth.server.jboss} &amp;&amp; ! ${auth.server.crossdc}</property>
<property name="adapterImplClass">${auth.server.adapter.impl.class}</property>
<property name="jbossHome">${auth.server.home}</property>
<property name="${auth.server.config.property.name}">${auth.server.config.property.value}</property>
@ -186,18 +186,18 @@
</group>
<!-- Cross DC with embedded undertow. Node numbering is [centre #].[node #] -->
<group qualifier="auth-server-undertow-cross-dc">
<!-- Cross DC. Node numbering is [centre #].[node #] -->
<group qualifier="auth-server-jboss-cross-dc">
<container qualifier="cache-server-cross-dc-1" mode="suite" >
<configuration>
<property name="enabled">${auth.server.undertow.crossdc} &amp;&amp; ! ${cache.server.lifecycle.skip}</property>
<property name="enabled">${auth.server.crossdc} &amp;&amp; ! ${cache.server.lifecycle.skip}</property>
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
<property name="jbossHome">${cache.server.home}</property>
<property name="serverConfig">clustered.xml</property>
<property name="jbossArguments">
-Djboss.socket.binding.port-offset=${cache.server.port.offset}
-Djboss.default.multicast.address=234.56.78.99
-Djboss.node.name=cache-server
-Djboss.node.name=cache-server-dc-1
${adapter.test.props}
${auth.server.profile}
</property>
@ -213,7 +213,7 @@
<container qualifier="cache-server-cross-dc-2" mode="suite" >
<configuration>
<property name="enabled">${auth.server.undertow.crossdc} &amp;&amp; ! ${cache.server.lifecycle.skip}</property>
<property name="enabled">${auth.server.crossdc} &amp;&amp; ! ${cache.server.lifecycle.skip}</property>
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
<property name="jbossHome">${cache.server.home}</property>
<property name="setupCleanServerBaseDir">true</property>
@ -238,11 +238,11 @@
<container qualifier="auth-server-balancer-cross-dc" mode="suite" >
<configuration>
<property name="enabled">${auth.server.undertow.crossdc}</property>
<property name="enabled">${auth.server.crossdc}</property>
<property name="adapterImplClass">org.keycloak.testsuite.arquillian.undertow.lb.SimpleUndertowLoadBalancerContainer</property>
<property name="bindAddress">localhost</property>
<property name="bindHttpPort">${auth.server.http.port}</property>
<property name="nodes">auth-server-undertow-cross-dc-0_1=http://localhost:8101,auth-server-undertow-cross-dc-0_2-manual=http://localhost:8102,auth-server-undertow-cross-dc-1_1=http://localhost:8111,auth-server-undertow-cross-dc-1_2-manual=http://localhost:8112</property>
<property name="nodes">auth-server-${node.name}-cross-dc-0_1=http://localhost:8101,auth-server-${node.name}-cross-dc-0_2-manual=http://localhost:8102,auth-server-${node.name}-cross-dc-1_1=http://localhost:8111,auth-server-${node.name}-cross-dc-1_2-manual=http://localhost:8112</property>
</configuration>
</container>
@ -253,7 +253,6 @@
<property name="bindAddress">localhost</property>
<property name="bindHttpPort">${auth.server.http.port}</property>
<property name="bindHttpPortOffset">-79</property>
<property name="route">auth-server-undertow-cross-dc-0_1</property>
<property name="remoteMode">${undertow.remote}</property>
<property name="dataCenter">0</property>
<property name="keycloakConfigPropertyOverrides">{
@ -277,7 +276,6 @@
<property name="bindAddress">localhost</property>
<property name="bindHttpPort">${auth.server.http.port}</property>
<property name="bindHttpPortOffset">-78</property>
<property name="route">auth-server-undertow-cross-dc-0_2-manual</property>
<property name="remoteMode">${undertow.remote}</property>
<property name="dataCenter">0</property>
<property name="keycloakConfigPropertyOverrides">{
@ -302,7 +300,6 @@
<property name="bindAddress">localhost</property>
<property name="bindHttpPort">${auth.server.http.port}</property>
<property name="bindHttpPortOffset">-69</property>
<property name="route">auth-server-undertow-cross-dc-1_1</property>
<property name="remoteMode">${undertow.remote}</property>
<property name="dataCenter">1</property>
<property name="keycloakConfigPropertyOverrides">{
@ -326,7 +323,6 @@
<property name="bindAddress">localhost</property>
<property name="bindHttpPort">${auth.server.http.port}</property>
<property name="bindHttpPortOffset">-68</property>
<property name="route">auth-server-undertow-cross-dc-1_2-manual</property>
<property name="remoteMode">${undertow.remote}</property>
<property name="dataCenter">1</property>
<property name="keycloakConfigPropertyOverrides">{
@ -343,8 +339,97 @@
}</property>
</configuration>
</container>
</group>
<container qualifier="auth-server-jboss-cross-dc-0_1" mode="suite" >
<configuration>
<property name="enabled">${auth.server.jboss.crossdc}</property>
<property name="adapterImplClass">${auth.server.adapter.impl.class}</property>
<property name="jbossHome">${auth.server.crossdc01.home}</property>
<property name="serverConfig">standalone-ha.xml</property>
<property name="jbossArguments">
-Djboss.socket.binding.port-offset=${auth.server.crossdc01.port.offset}
-Djboss.default.multicast.address=234.56.78.1
-Dremote.cache.port=12232
-Djboss.site.name=dc0
-Djboss.node.name=auth-server-${node.name}-cross-dc-0_1
</property>
<property name="javaVmArguments">
-Djava.net.preferIPv4Stack=true
${auth.server.crossdc01.jvm.debug.args}
</property>
<property name="managementPort">${auth.server.crossdc01.management.port}</property>
<property name="bindHttpPortOffset">-79</property>
<property name="dataCenter">0</property>
</configuration>
</container>
<container qualifier="auth-server-jboss-cross-dc-0_2-manual" mode="manual" >
<configuration>
<property name="enabled">${auth.server.jboss.crossdc}</property>
<property name="adapterImplClass">${auth.server.adapter.impl.class}</property>
<property name="jbossHome">${auth.server.crossdc02.home}</property>
<property name="serverConfig">standalone-ha.xml</property>
<property name="jbossArguments">
-Djboss.socket.binding.port-offset=${auth.server.crossdc02.port.offset}
-Djboss.default.multicast.address=234.56.78.1
-Dremote.cache.port=12232
-Djboss.site.name=dc0
-Djboss.node.name=auth-server-${node.name}-cross-dc-0_2-manual
</property>
<property name="javaVmArguments">
-Djava.net.preferIPv4Stack=true
${auth.server.crossdc02.jvm.debug.args}
</property>
<property name="managementPort">${auth.server.crossdc02.management.port}</property>
<property name="bindHttpPortOffset">-78</property>
<property name="dataCenter">0</property>
</configuration>
</container>
<container qualifier="auth-server-jboss-cross-dc-1_1" mode="suite" >
<configuration>
<property name="enabled">${auth.server.jboss.crossdc}</property>
<property name="adapterImplClass">${auth.server.adapter.impl.class}</property>
<property name="jbossHome">${auth.server.crossdc11.home}</property>
<property name="serverConfig">standalone-ha.xml</property>
<property name="jbossArguments">
-Djboss.socket.binding.port-offset=${auth.server.crossdc11.port.offset}
-Djboss.default.multicast.address=234.56.78.2
-Dremote.cache.port=13232
-Djboss.site.name=dc1
-Djboss.node.name=auth-server-${node.name}-cross-dc-1_1
</property>
<property name="javaVmArguments">
-Djava.net.preferIPv4Stack=true
${auth.server.crossdc11.jvm.debug.args}
</property>
<property name="managementPort">${auth.server.crossdc11.management.port}</property>
<property name="bindHttpPortOffset">-69</property>
<property name="dataCenter">1</property>
</configuration>
</container>
<container qualifier="auth-server-jboss-cross-dc-1_2-manual" mode="manual" >
<configuration>
<property name="enabled">${auth.server.jboss.crossdc}</property>
<property name="adapterImplClass">${auth.server.adapter.impl.class}</property>
<property name="jbossHome">${auth.server.crossdc12.home}</property>
<property name="serverConfig">standalone-ha.xml</property>
<property name="jbossArguments">
-Djboss.socket.binding.port-offset=${auth.server.crossdc12.port.offset}
-Djboss.default.multicast.address=234.56.78.2
-Dremote.cache.port=13232
-Djboss.site.name=dc1
-Djboss.node.name=auth-server-${node.name}-cross-dc-1_2-manual
</property>
<property name="javaVmArguments">
-Djava.net.preferIPv4Stack=true
${auth.server.crossdc12.jvm.debug.args}
</property>
<property name="managementPort">${auth.server.crossdc12.management.port}</property>
<property name="bindHttpPortOffset">-68</property>
<property name="dataCenter">1</property>
</configuration>
</container>
</group>
<container qualifier="auth-server-balancer-wildfly" mode="suite" >
<configuration>

View file

@ -41,10 +41,12 @@
<properties>
<auth.server>undertow</auth.server>
<auth.server.undertow>true</auth.server.undertow>
<auth.server.undertow.crossdc>false</auth.server.undertow.crossdc>
<auth.server.crossdc>false</auth.server.crossdc>
<auth.server.undertow.crossdc>false</auth.server.undertow.crossdc>
<auth.server.jboss.crossdc>false</auth.server.jboss.crossdc>
<cache.server.lifecycle.skip>false</cache.server.lifecycle.skip>
<auth.server.container>auth-server-${auth.server}</auth.server.container>
<auth.server.home>${containers.home}/${auth.server.container}</auth.server.home>
<auth.server.config.dir>${auth.server.home}</auth.server.config.dir>
@ -60,16 +62,16 @@
<auth.server.memory.settings>-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m</auth.server.memory.settings>
<auth.server.config.property.name>serverConfig</auth.server.config.property.name>
<auth.server.adapter.impl.class>org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</auth.server.adapter.impl.class>
<auth.server.jboss.artifactId>integration-arquillian-servers-auth-server-${auth.server}</auth.server.jboss.artifactId>
<auth.server.jboss.skip.unpack>${auth.server.undertow}</auth.server.jboss.skip.unpack>
<auth.server.jboss.startup.timeout>300</auth.server.jboss.startup.timeout>
<!--debug properties-->
<auth.server.debug.port>5005</auth.server.debug.port>
<auth.server.debug.suspend>n</auth.server.debug.suspend>
<auth.server.jboss.jvm.debug.args>-agentlib:jdwp=transport=dt_socket,server=y,suspend=${auth.server.debug.suspend},address=${auth.server.host}:${auth.server.debug.port}</auth.server.jboss.jvm.debug.args>
<auth.server.remote>false</auth.server.remote>
<auth.server.profile/>
<auth.server.feature/>
@ -91,7 +93,7 @@
<adapter.test.props/>
<migration.import.properties/>
<kie.maven.settings/>
<examples.home>${project.build.directory}/examples</examples.home>
<browser>htmlUnit</browser>
@ -242,10 +244,10 @@
<auth.server.config.property.value>${auth.server.config.property.value}</auth.server.config.property.value>
<auth.server.adapter.impl.class>${auth.server.adapter.impl.class}</auth.server.adapter.impl.class>
<auth.server.jboss.jvm.debug.args>${auth.server.jboss.jvm.debug.args}</auth.server.jboss.jvm.debug.args>
<auth.server.profile>${auth.server.profile}</auth.server.profile>
<auth.server.feature>${auth.server.feature}</auth.server.feature>
<frontend.console.output>${frontend.console.output}</frontend.console.output>
<backends.console.output>${backend.console.output}</backends.console.output>
@ -254,7 +256,7 @@
<adapter.test.props>${adapter.test.props}</adapter.test.props>
<migration.import.properties>${migration.import.properties}</migration.import.properties>
<kie.maven.settings>${kie.maven.settings}</kie.maven.settings>
<testsuite.constants>${testsuite.constants}</testsuite.constants>
<cli.log.output>${cli.log.output}</cli.log.output>
<test.intermittent>${test.intermittent}</test.intermittent>
@ -287,10 +289,11 @@
<client.key.passphrase>${client.key.passphrase}</client.key.passphrase>
<auth.server.ocsp.responder.enabled>${auth.server.ocsp.responder.enabled}</auth.server.ocsp.responder.enabled>
<!--cache server properties-->
<auth.server.crossdc>${auth.server.crossdc}</auth.server.crossdc>
<auth.server.undertow.crossdc>${auth.server.undertow.crossdc}</auth.server.undertow.crossdc>
<auth.server.jboss.crossdc>${auth.server.jboss.crossdc}</auth.server.jboss.crossdc>
<cache.server.lifecycle.skip>${cache.server.lifecycle.skip}</cache.server.lifecycle.skip>
<cache.server>${cache.server}</cache.server>
@ -367,14 +370,13 @@
</dependency>
</dependencies>
</profile>
<profile>
<id>auth-server-wildfly</id>
<properties>
<auth.server>wildfly</auth.server>
<auth.server.jboss>true</auth.server.jboss>
<auth.server.undertow>false</auth.server.undertow>
<auth.server.undertow.crossdc>false</auth.server.undertow.crossdc>
<auth.server.config.property.value>standalone.xml</auth.server.config.property.value>
<auth.server.config.dir>${auth.server.home}/standalone/configuration</auth.server.config.dir>
<h2.version>1.3.173</h2.version>
@ -393,7 +395,6 @@
<auth.server>eap</auth.server>
<auth.server.jboss>true</auth.server.jboss>
<auth.server.undertow>false</auth.server.undertow>
<auth.server.undertow.crossdc>false</auth.server.undertow.crossdc>
<auth.server.config.property.value>standalone.xml</auth.server.config.property.value>
<auth.server.config.dir>${auth.server.home}/standalone/configuration</auth.server.config.dir>
<h2.version>1.3.173</h2.version>
@ -406,14 +407,192 @@
</dependencies>
</profile>
<profile>
<id>auth-servers-crossdc-undertow</id>
<properties>
<auth.servers.crossdc>true</auth.servers.crossdc>
<auth.server.undertow.crossdc>true</auth.server.undertow.crossdc>
<node.name>undertow</node.name>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-profile-activation</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>cache.server.jboss</property>
<message>Profile "auth-servers-crossdc-undertow" requires activation of another profile: either "cache-server-infinispan" or "cache-server-jdg".</message>
<regex>true</regex>
</requireProperty>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<node.name>${node.name}</node.name>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>auth-servers-crossdc-jboss</id>
<properties>
<auth.servers.crossdc>true</auth.servers.crossdc>
<auth.server.jboss.crossdc>true</auth.server.jboss.crossdc>
<node.name>jboss</node.name>
<auth.server.crossdc01.home>${containers.home}/auth-server-${auth.server}-crossdc01</auth.server.crossdc01.home>
<auth.server.crossdc02.home>${containers.home}/auth-server-${auth.server}-crossdc02</auth.server.crossdc02.home>
<auth.server.crossdc11.home>${containers.home}/auth-server-${auth.server}-crossdc11</auth.server.crossdc11.home>
<auth.server.crossdc12.home>${containers.home}/auth-server-${auth.server}-crossdc12</auth.server.crossdc12.home>
<!-- property specifies keycloak-add-user.json file destination -->
<auth.server.config.dir>${auth.server.crossdc01.home}/standalone/configuration</auth.server.config.dir>
<auth.server.crossdc01.jvm.debug.port>5001</auth.server.crossdc01.jvm.debug.port>
<auth.server.crossdc02.jvm.debug.port>5002</auth.server.crossdc02.jvm.debug.port>
<auth.server.crossdc11.jvm.debug.port>5011</auth.server.crossdc11.jvm.debug.port>
<auth.server.crossdc12.jvm.debug.port>5012</auth.server.crossdc12.jvm.debug.port>
<!-- default is "n", possible to override by e.g. -Dauth.server.crossdc01.debug.suspend=y -->
<auth.server.crossdc01.debug.suspend>${auth.server.debug.suspend}</auth.server.crossdc01.debug.suspend>
<auth.server.crossdc02.debug.suspend>${auth.server.debug.suspend}</auth.server.crossdc02.debug.suspend>
<auth.server.crossdc11.debug.suspend>${auth.server.debug.suspend}</auth.server.crossdc11.debug.suspend>
<auth.server.crossdc12.debug.suspend>${auth.server.debug.suspend}</auth.server.crossdc12.debug.suspend>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy-auth-server-crossdc-nodes</id>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<move todir="${auth.server.crossdc01.home}">
<fileset dir="${auth.server.home}"/>
</move>
<copy todir="${auth.server.crossdc02.home}">
<fileset dir="${auth.server.crossdc01.home}"/>
</copy>
<copy todir="${auth.server.crossdc11.home}">
<fileset dir="${auth.server.crossdc01.home}"/>
</copy>
<copy todir="${auth.server.crossdc12.home}">
<fileset dir="${auth.server.crossdc01.home}"/>
</copy>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-profiles-activation</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>cache.server.jboss</property>
<message>Profile "auth-servers-crossdc-jboss" requires activation of another profile: either "cache-server-infinispan" or "cache-server-jdg".</message>
<regex>true</regex>
</requireProperty>
<requireProperty>
<property>auth.server.jboss</property>
<message>Profile "auth-servers-crossdc-jboss" requires activation of another profile: either "auth-server-wildfly" or "auth-server-eap".</message>
<regex>true</regex>
</requireProperty>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<run.h2>true</run.h2>
<node.name>${node.name}</node.name>
<auth.server.crossdc01.home>${auth.server.crossdc01.home}</auth.server.crossdc01.home>
<auth.server.crossdc02.home>${auth.server.crossdc02.home}</auth.server.crossdc02.home>
<auth.server.crossdc11.home>${auth.server.crossdc11.home}</auth.server.crossdc11.home>
<auth.server.crossdc12.home>${auth.server.crossdc12.home}</auth.server.crossdc12.home>
<!--8101-->
<auth.server.crossdc01.port.offset>21</auth.server.crossdc01.port.offset>
<!--8102-->
<auth.server.crossdc02.port.offset>22</auth.server.crossdc02.port.offset>
<!--8111-->
<auth.server.crossdc11.port.offset>31</auth.server.crossdc11.port.offset>
<!--8112-->
<auth.server.crossdc12.port.offset>32</auth.server.crossdc12.port.offset>
<auth.server.crossdc01.management.port>10011</auth.server.crossdc01.management.port>
<auth.server.crossdc02.management.port>10012</auth.server.crossdc02.management.port>
<auth.server.crossdc11.management.port>10021</auth.server.crossdc11.management.port>
<auth.server.crossdc12.management.port>10022</auth.server.crossdc12.management.port>
<auth.server.crossdc01.jvm.debug.args>
-agentlib:jdwp=transport=dt_socket,server=y,suspend=${auth.server.crossdc01.debug.suspend},address=localhost:${auth.server.crossdc01.jvm.debug.port}
</auth.server.crossdc01.jvm.debug.args>
<auth.server.crossdc02.jvm.debug.args>
-agentlib:jdwp=transport=dt_socket,server=y,suspend=${auth.server.crossdc02.debug.suspend},address=localhost:${auth.server.crossdc02.jvm.debug.port}
</auth.server.crossdc02.jvm.debug.args>
<auth.server.crossdc11.jvm.debug.args>
-agentlib:jdwp=transport=dt_socket,server=y,suspend=${auth.server.crossdc11.debug.suspend},address=localhost:${auth.server.crossdc11.jvm.debug.port}
</auth.server.crossdc11.jvm.debug.args>
<auth.server.crossdc12.jvm.debug.args>
-agentlib:jdwp=transport=dt_socket,server=y,suspend=${auth.server.crossdc12.debug.suspend},address=localhost:${auth.server.crossdc12.jvm.debug.port}
</auth.server.crossdc12.jvm.debug.args>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<configuration>
<skip>${skipTests}</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>cache-server-infinispan</id>
<properties>
<cache.server>infinispan</cache.server>
<auth.server.undertow.crossdc>true</auth.server.undertow.crossdc>
<auth.server.crossdc>true</auth.server.crossdc>
<cache.server.jboss>true</cache.server.jboss>
<cache.server.config.dir>${cache.server.home}/standalone/configuration</cache.server.config.dir>
<cache.server.config.dir>${cache.server.home}/standalone/configuration</cache.server.config.dir>
<keycloak.testsuite.logging.pattern>%d{HH:mm:ss,SSS} [%t] %-5p [%c{1.}] %m%n</keycloak.testsuite.logging.pattern>
</properties>
<dependencies>
@ -429,17 +608,15 @@
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-profile-activation</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<!--requireActiveProfile 'auth-server-wildfly/eap' doesn't work unless the profiles are defined in all submodule poms
using requireProperty instead-->
<requireProperty>
<property>cache.server</property>
<regex>(infinispan)|(jdg)</regex>
<regexMessage>Profile "cache-server-infinispan" requires activation of profile "cache-server-infinispan" or "cache-server-jdg".</regexMessage>
<property>auth.servers.crossdc</property>
<message>Profile "cache-server-infinispan" requires activation of another profile: either "auth-servers-crossdc-undertow" or "auth-servers-crossdc-jboss".</message>
</requireProperty>
</rules>
</configuration>
@ -480,12 +657,11 @@
</pluginManagement>
</build>
</profile>
<profile>
<id>cache-server-jdg</id>
<properties>
<cache.server>jdg</cache.server>
<auth.server.undertow.crossdc>true</auth.server.undertow.crossdc>
<auth.server.crossdc>true</auth.server.crossdc>
<cache.server.jboss>true</cache.server.jboss>
<cache.server.config.dir>${cache.server.home}/standalone/configuration</cache.server.config.dir>
@ -504,17 +680,15 @@
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-profile-activation</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<!--requireActiveProfile 'auth-server-wildfly/eap' doesn't work unless the profiles are defined in all submodule poms
using requireProperty instead-->
<requireProperty>
<property>cache.server</property>
<regex>(infinispan)|(jdg)</regex>
<regexMessage>Profile "cache-server-jdg" requires activation of profile "cache-server-infinispan" or "cache-server-jdg".</regexMessage>
<property>auth.servers.crossdc</property>
<message>Profile "cache-server-jdg" requires activation of another profile: either "auth-servers-crossdc-undertow" or "auth-servers-crossdc-jboss".</message>
</requireProperty>
</rules>
</configuration>
@ -569,8 +743,8 @@
</profile>
<!--
profile that enables/disables specified feature, for more details see
https://keycloak.gitbooks.io/documentation/content/server_installation/topics/profiles.html
profile that enables/disables specified feature, for more details see
https://keycloak.gitbooks.io/documentation/content/server_installation/topics/profiles.html
-->
<profile>
<id>auth-server-enable-disable-feature</id>
@ -765,7 +939,7 @@
</pluginManagement>
</build>
</profile>
<profile>
<id>jdbc-driver-dependency</id>
<activation>
@ -807,13 +981,13 @@
</profile>
<!-- Profiles for migration tests-->
<profile>
<id>auth-server-migration</id>
<properties>
<migration.import.file>target/test-classes/migration-test/migration-realm-${migrated.auth.server.version}.json</migration.import.file>
<migration.import.props.previous>
-Dkeycloak.migration.action=import
-Dkeycloak.migration.action=import
-Dkeycloak.migration.provider=singleFile
-Dkeycloak.migration.file=${migration.import.file}
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING
@ -883,8 +1057,8 @@
</plugins>
</pluginManagement>
</build>
</profile>
</profile>
<profile>
<id>migration-import</id>
<activation>
@ -896,7 +1070,7 @@
<properties>
<migration.import.file>target/test-classes/migration-test/migration-realm-${migrated.auth.server.version}.json</migration.import.file>
<migration.import.properties>
-Dkeycloak.migration.action=import
-Dkeycloak.migration.action=import
-Dkeycloak.migration.provider=singleFile
-Dkeycloak.migration.file=${migration.import.file}
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING
@ -934,7 +1108,7 @@
</plugins>
</build>
</profile>
<profile>
<id>migration-productized</id>
<activation>
@ -946,7 +1120,7 @@
<migration.import.file>target/test-classes/migration-test/migration-realm-${migrated.version.import.file.suffix}.json</migration.import.file>
</properties>
</profile>
<profile>
<id>no-account</id>
<properties>
@ -1280,7 +1454,7 @@
<auth.server.management.port.jmx>9999</auth.server.management.port.jmx>
</properties>
</profile>
<profile>
<!--see KEYCLOAK-4793-->
<id>kie.maven.settings</id>
@ -1299,7 +1473,7 @@
</kie.maven.settings>
</properties>
</profile>
</profiles>
</project>