Remove possibility to start embedded HotRod server in hotrod-map module
Closes #13247
This commit is contained in:
parent
cf249fc6ae
commit
ec808d28bb
13 changed files with 163 additions and 140 deletions
|
@ -30,18 +30,6 @@
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-remote-query-client</artifactId>
|
<artifactId>infinispan-remote-query-client</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-server-router</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-server-rest</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-server-runtime</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan.protostream</groupId>
|
<groupId>org.infinispan.protostream</groupId>
|
||||||
<artifactId>protostream-processor</artifactId>
|
<artifactId>protostream-processor</artifactId>
|
||||||
|
|
|
@ -16,26 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.map.storage.hotRod.common;
|
package org.keycloak.models.map.storage.hotRod.common;
|
||||||
|
|
||||||
import org.infinispan.manager.DefaultCacheManager;
|
|
||||||
import org.infinispan.query.dsl.Query;
|
import org.infinispan.query.dsl.Query;
|
||||||
import org.infinispan.rest.RestServer;
|
|
||||||
import org.infinispan.rest.configuration.RestServerConfigurationBuilder;
|
|
||||||
import org.infinispan.server.configuration.endpoint.SinglePortServerConfigurationBuilder;
|
|
||||||
import org.infinispan.server.hotrod.HotRodServer;
|
|
||||||
import org.infinispan.server.hotrod.configuration.HotRodServerConfigurationBuilder;
|
|
||||||
import org.infinispan.server.router.RoutingTable;
|
|
||||||
import org.infinispan.server.router.configuration.SinglePortRouterConfiguration;
|
|
||||||
import org.infinispan.server.router.router.impl.singleport.SinglePortEndpointRouter;
|
|
||||||
import org.infinispan.server.router.routes.Route;
|
|
||||||
import org.infinispan.server.router.routes.RouteDestination;
|
|
||||||
import org.infinispan.server.router.routes.RouteSource;
|
|
||||||
import org.infinispan.server.router.routes.hotrod.HotRodServerRouteDestination;
|
|
||||||
import org.infinispan.server.router.routes.rest.RestServerRouteDestination;
|
|
||||||
import org.infinispan.server.router.routes.singleport.SinglePortRouteSource;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
* @author <a href="mailto:mkanis@redhat.com">Martin Kanis</a>
|
||||||
|
@ -44,51 +25,6 @@ public class HotRodUtils {
|
||||||
|
|
||||||
public static final int DEFAULT_MAX_RESULTS = Integer.MAX_VALUE >> 1;
|
public static final int DEFAULT_MAX_RESULTS = Integer.MAX_VALUE >> 1;
|
||||||
|
|
||||||
/**
|
|
||||||
* Not suitable for a production usage. Only for development and test purposes.
|
|
||||||
* Also do not use in clustered environment.
|
|
||||||
* @param hotRodServer HotRodServer
|
|
||||||
* @param hotRodCacheManager DefaultCacheManager
|
|
||||||
* @param embeddedPort int
|
|
||||||
*/
|
|
||||||
public static void createHotRodMapStoreServer(HotRodServer hotRodServer, DefaultCacheManager hotRodCacheManager, int embeddedPort) {
|
|
||||||
HotRodServerConfigurationBuilder hotRodServerConfigurationBuilder = new HotRodServerConfigurationBuilder();
|
|
||||||
hotRodServerConfigurationBuilder.startTransport(false);
|
|
||||||
hotRodServerConfigurationBuilder.port(embeddedPort);
|
|
||||||
hotRodServer.start(hotRodServerConfigurationBuilder.build(), hotRodCacheManager);
|
|
||||||
|
|
||||||
RestServerConfigurationBuilder restServerConfigurationBuilder = new RestServerConfigurationBuilder();
|
|
||||||
restServerConfigurationBuilder.startTransport(false);
|
|
||||||
restServerConfigurationBuilder.port(embeddedPort);
|
|
||||||
RestServer restServer = new RestServer();
|
|
||||||
restServer.start(restServerConfigurationBuilder.build(), hotRodCacheManager);
|
|
||||||
|
|
||||||
SinglePortRouteSource routeSource = new SinglePortRouteSource();
|
|
||||||
Set<Route<? extends RouteSource, ? extends RouteDestination>> routes = new HashSet<>();
|
|
||||||
routes.add(new Route<>(routeSource, new HotRodServerRouteDestination("hotrod", hotRodServer)));
|
|
||||||
routes.add(new Route<>(routeSource, new RestServerRouteDestination("rest", restServer)));
|
|
||||||
|
|
||||||
SinglePortRouterConfiguration singlePortRouter = new SinglePortServerConfigurationBuilder().port(embeddedPort).build();
|
|
||||||
SinglePortEndpointRouter endpointServer = new SinglePortEndpointRouter(singlePortRouter);
|
|
||||||
endpointServer.start(new RoutingTable(routes));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not suitable for a production usage. Only for development and test purposes.
|
|
||||||
* Also do not use in clustered environment.
|
|
||||||
* @param embeddedPort int
|
|
||||||
*/
|
|
||||||
public static void createHotRodMapStoreServer(int embeddedPort) {
|
|
||||||
DefaultCacheManager hotRodCacheManager = null;
|
|
||||||
try {
|
|
||||||
hotRodCacheManager = new DefaultCacheManager("config/infinispan.xml");
|
|
||||||
} catch (IOException e) {
|
|
||||||
new RuntimeException("Cannot initialize cache manager!", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
HotRodUtils.createHotRodMapStoreServer(new HotRodServer(), hotRodCacheManager, embeddedPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Query<T> paginateQuery(Query<T> query, Integer first, Integer max) {
|
public static <T> Query<T> paginateQuery(Query<T> query, Integer first, Integer max) {
|
||||||
if (first != null && first > 0) {
|
if (first != null && first > 0) {
|
||||||
query = query.startOffset(first);
|
query = query.startOffset(first);
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.map.storage.hotRod.common.HotRodEntityDescriptor;
|
import org.keycloak.models.map.storage.hotRod.common.HotRodEntityDescriptor;
|
||||||
import org.keycloak.models.map.storage.hotRod.common.HotRodUtils;
|
|
||||||
import org.keycloak.models.map.storage.hotRod.common.CommonPrimitivesProtoSchemaInitializer;
|
import org.keycloak.models.map.storage.hotRod.common.CommonPrimitivesProtoSchemaInitializer;
|
||||||
import org.keycloak.models.map.storage.hotRod.common.HotRodVersionUtils;
|
import org.keycloak.models.map.storage.hotRod.common.HotRodVersionUtils;
|
||||||
|
|
||||||
|
@ -89,14 +88,10 @@ public class DefaultHotRodConnectionProviderFactory implements HotRodConnectionP
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lazyInit() {
|
public void lazyInit() {
|
||||||
if (config.getBoolean("embedded", false)) {
|
|
||||||
HotRodUtils.createHotRodMapStoreServer(config.getInt("embeddedPort", 11444));
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigurationBuilder remoteBuilder = new ConfigurationBuilder();
|
ConfigurationBuilder remoteBuilder = new ConfigurationBuilder();
|
||||||
remoteBuilder.addServer()
|
remoteBuilder.addServer()
|
||||||
.host(config.get("host", "localhost"))
|
.host(config.get("host", "localhost"))
|
||||||
.port(config.getInt("port", 11444))
|
.port(config.getInt("port", 11222))
|
||||||
.clientIntelligence(ClientIntelligence.HASH_DISTRIBUTION_AWARE)
|
.clientIntelligence(ClientIntelligence.HASH_DISTRIBUTION_AWARE)
|
||||||
.marshaller(new ProtoStreamMarshaller());
|
.marshaller(new ProtoStreamMarshaller());
|
||||||
|
|
||||||
|
|
1
pom.xml
1
pom.xml
|
@ -178,6 +178,7 @@
|
||||||
https://issues.redhat.com/browse/KEYCLOAK-17585?focusedCommentId=16002705&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-16002705
|
https://issues.redhat.com/browse/KEYCLOAK-17585?focusedCommentId=16002705&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-16002705
|
||||||
-->
|
-->
|
||||||
<microprofile-metrics-api.version>2.3</microprofile-metrics-api.version>
|
<microprofile-metrics-api.version>2.3</microprofile-metrics-api.version>
|
||||||
|
<testcontainers.version>1.16.3</testcontainers.version>
|
||||||
|
|
||||||
<!-- Maven Plugins -->
|
<!-- Maven Plugins -->
|
||||||
<replacer.plugin.version>1.3.5</replacer.plugin.version>
|
<replacer.plugin.version>1.3.5</replacer.plugin.version>
|
||||||
|
|
|
@ -469,28 +469,6 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-server-rest</artifactId>
|
|
||||||
<version>${infinispan.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.infinispan</groupId>
|
|
||||||
<artifactId>infinispan-server-router</artifactId>
|
|
||||||
<version>${infinispan.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.infinispan</groupId>
|
<groupId>org.infinispan</groupId>
|
||||||
<artifactId>infinispan-cachestore-remote</artifactId>
|
<artifactId>infinispan-cachestore-remote</artifactId>
|
||||||
|
|
|
@ -55,7 +55,6 @@
|
||||||
<arquillian-tomcat9-container-version>1.1.0.Final</arquillian-tomcat9-container-version>
|
<arquillian-tomcat9-container-version>1.1.0.Final</arquillian-tomcat9-container-version>
|
||||||
<undertow-embedded.version>1.0.0.Alpha2</undertow-embedded.version>
|
<undertow-embedded.version>1.0.0.Alpha2</undertow-embedded.version>
|
||||||
<version.org.wildfly.extras.creaper>1.6.1</version.org.wildfly.extras.creaper>
|
<version.org.wildfly.extras.creaper>1.6.1</version.org.wildfly.extras.creaper>
|
||||||
<testcontainers.version>1.5.1</testcontainers.version>
|
|
||||||
<appium.client.version>6.1.0</appium.client.version>
|
<appium.client.version>6.1.0</appium.client.version>
|
||||||
|
|
||||||
<!--migration properties-->
|
<!--migration properties-->
|
||||||
|
|
|
@ -48,3 +48,59 @@ mvn test -Pjpa -Dtest=ClientModelTest \
|
||||||
```
|
```
|
||||||
|
|
||||||
The results are available in the `target/profile.html` file.
|
The results are available in the `target/profile.html` file.
|
||||||
|
|
||||||
|
Usage of Testcontainers
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Some profiles within model tests require running 3rd party software, for
|
||||||
|
example, database or Infinispan. For running these we are using
|
||||||
|
[Testcontainers](https://www.testcontainers.org/). This may require some
|
||||||
|
additional configuration of your container engine.
|
||||||
|
|
||||||
|
#### Podman settings
|
||||||
|
|
||||||
|
For more details see the following [Podman guide from Quarkus webpage](https://quarkus.io/guides/podman).
|
||||||
|
|
||||||
|
Specifically, these steps are required:
|
||||||
|
```shell
|
||||||
|
# Enable the podman socket with Docker REST API (only needs to be done once)
|
||||||
|
systemctl --user enable podman.socket --now
|
||||||
|
|
||||||
|
# Set the required environment variables (need to be run everytime or added to profile)
|
||||||
|
export DOCKER_HOST=unix:///run/user/${UID}/podman/podman.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
Testcontainers are using [ryuk](https://hub.docker.com/r/testcontainers/ryuk)
|
||||||
|
to cleanup containers after tests. To make this work with Podman add the
|
||||||
|
following line to `~/.testcontainers.properties`
|
||||||
|
```shell
|
||||||
|
ryuk.container.privileged=true
|
||||||
|
```
|
||||||
|
Alternatively, disable usage of ryuk (using this may result in stale containers
|
||||||
|
still running after tests finish. This is not recommended especially if you are
|
||||||
|
executing tests from Intellij IDE as it [may not stop](https://youtrack.jetbrains.com/issue/IDEA-190385)
|
||||||
|
the containers created during test run).
|
||||||
|
```shell
|
||||||
|
export TESTCONTAINERS_RYUK_DISABLED=true #not recommended - see above!
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Docker settings
|
||||||
|
|
||||||
|
To use Testcontainers with Docker it is necessary to
|
||||||
|
[make Docker available for non-root users](https://docs.docker.com/engine/install/linux-postinstall/).
|
||||||
|
|
||||||
|
Running HotRod tests with external Infinispan
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
By default, Model tests with `hot-rod` profile spawn a new Infinispan container
|
||||||
|
with each test execution. It is also possible, to configure Model tests to
|
||||||
|
connect to an external instance of Infinispan. To do so, execute tests with
|
||||||
|
the following command:
|
||||||
|
```shell
|
||||||
|
mvn test -Phot-rod \
|
||||||
|
-Dhot-rod.start-container=false \
|
||||||
|
-Dhot-rod.connection.host=<host> \
|
||||||
|
-Dhot-rod.connection.port=<port> \
|
||||||
|
-Dhot-rod.connection.username=<username> \
|
||||||
|
-Dhot-rod.connection.password=<password>
|
||||||
|
```
|
||||||
|
|
|
@ -120,6 +120,12 @@
|
||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<version>${postgresql.driver.version}</version>
|
<version>${postgresql.driver.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testcontainers</groupId>
|
||||||
|
<artifactId>testcontainers</artifactId>
|
||||||
|
<version>${testcontainers.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -171,7 +177,14 @@
|
||||||
<keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase>${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase}</keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase>
|
<keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase>${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase}</keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase>
|
||||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
<org.jboss.logging.provider>log4j</org.jboss.logging.provider>
|
<org.jboss.logging.provider>log4j</org.jboss.logging.provider>
|
||||||
|
<infinispan.version>${infinispan.version}</infinispan.version>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
|
<properties>
|
||||||
|
<property>
|
||||||
|
<name>listener</name>
|
||||||
|
<value>org.keycloak.testsuite.model.AfterSuiteListener</value>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|
|
@ -84,29 +84,6 @@ public class HotRodServerRule extends ExternalResource {
|
||||||
InfinispanUtil.setTimeServiceToKeycloakTime(hotRodCacheManager2);
|
InfinispanUtil.setTimeServiceToKeycloakTime(hotRodCacheManager2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createHotRodMapStoreServer() {
|
|
||||||
hotRodCacheManager = configureHotRodCacheManager("hotrod/infinispan.xml");
|
|
||||||
hotRodServer = new HotRodServer();
|
|
||||||
|
|
||||||
HotRodUtils.createHotRodMapStoreServer(hotRodServer, hotRodCacheManager, 11444);
|
|
||||||
|
|
||||||
org.infinispan.client.hotrod.configuration.ConfigurationBuilder remoteBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
|
|
||||||
org.infinispan.client.hotrod.configuration.Configuration cfg = remoteBuilder
|
|
||||||
.addServers(hotRodServer.getHost() + ":" + hotRodServer.getPort()).build();
|
|
||||||
remoteCacheManager = new RemoteCacheManager(cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DefaultCacheManager configureHotRodCacheManager(String configPath) {
|
|
||||||
DefaultCacheManager manager = null;
|
|
||||||
try {
|
|
||||||
manager = new DefaultCacheManager(configPath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getCaches(String... cache) {
|
private void getCaches(String... cache) {
|
||||||
for (String c: cache) {
|
for (String c: cache) {
|
||||||
hotRodCacheManager.getCache(c, true);
|
hotRodCacheManager.getCache(c, true);
|
||||||
|
|
|
@ -72,4 +72,8 @@ public class KeycloakModelParameters {
|
||||||
public void beforeSuite(Config cf) {
|
public void beforeSuite(Config cf) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void afterSuite() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.testsuite.model;
|
||||||
|
|
||||||
|
import org.junit.runner.Result;
|
||||||
|
import org.junit.runner.notification.RunListener;
|
||||||
|
|
||||||
|
public class AfterSuiteListener extends RunListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testRunFinished(Result result) throws Exception {
|
||||||
|
KeycloakModelTest.closeKeycloakSessionFactory();
|
||||||
|
for (KeycloakModelParameters kmp : KeycloakModelTest.MODEL_PARAMETERS) {
|
||||||
|
kmp.afterSuite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,8 +17,7 @@
|
||||||
package org.keycloak.testsuite.model.parameters;
|
package org.keycloak.testsuite.model.parameters;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import org.junit.runner.Description;
|
import org.jboss.logging.Logger;
|
||||||
import org.junit.runners.model.Statement;
|
|
||||||
import org.keycloak.authorization.store.StoreFactorySpi;
|
import org.keycloak.authorization.store.StoreFactorySpi;
|
||||||
import org.keycloak.events.EventStoreSpi;
|
import org.keycloak.events.EventStoreSpi;
|
||||||
import org.keycloak.models.ActionTokenStoreSpi;
|
import org.keycloak.models.ActionTokenStoreSpi;
|
||||||
|
@ -31,7 +30,6 @@ import org.keycloak.models.map.authSession.MapRootAuthenticationSessionProviderF
|
||||||
import org.keycloak.models.map.authorization.MapAuthorizationStoreFactory;
|
import org.keycloak.models.map.authorization.MapAuthorizationStoreFactory;
|
||||||
import org.keycloak.models.map.client.MapClientProviderFactory;
|
import org.keycloak.models.map.client.MapClientProviderFactory;
|
||||||
import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory;
|
import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory;
|
||||||
import org.keycloak.models.map.events.MapEventStoreProviderFactory;
|
|
||||||
import org.keycloak.models.map.keys.MapPublicKeyStorageProviderFactory;
|
import org.keycloak.models.map.keys.MapPublicKeyStorageProviderFactory;
|
||||||
import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory;
|
import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory;
|
||||||
import org.keycloak.models.map.storage.hotRod.connections.DefaultHotRodConnectionProviderFactory;
|
import org.keycloak.models.map.storage.hotRod.connections.DefaultHotRodConnectionProviderFactory;
|
||||||
|
@ -51,10 +49,14 @@ import org.keycloak.provider.ProviderFactory;
|
||||||
import org.keycloak.provider.Spi;
|
import org.keycloak.provider.Spi;
|
||||||
import org.keycloak.sessions.AuthenticationSessionSpi;
|
import org.keycloak.sessions.AuthenticationSessionSpi;
|
||||||
import org.keycloak.testsuite.model.Config;
|
import org.keycloak.testsuite.model.Config;
|
||||||
import org.keycloak.testsuite.model.HotRodServerRule;
|
|
||||||
import org.keycloak.testsuite.model.KeycloakModelParameters;
|
import org.keycloak.testsuite.model.KeycloakModelParameters;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -62,6 +64,24 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public class HotRodMapStorage extends KeycloakModelParameters {
|
public class HotRodMapStorage extends KeycloakModelParameters {
|
||||||
|
|
||||||
|
private final Logger LOG = Logger.getLogger(getClass());
|
||||||
|
public static final String PORT = System.getProperty("hot-rod.connection.port", "11222");
|
||||||
|
public static String HOST = System.getProperty("hot-rod.connection.host");
|
||||||
|
public static final String USERNAME = System.getProperty("hot-rod.connection.username", "admin");
|
||||||
|
public static final String PASSWORD = System.getProperty("hot-rod.connection.password", "admin");
|
||||||
|
public static final Boolean START_CONTAINER = Boolean.valueOf(System.getProperty("hot-rod.start-container", "true"));
|
||||||
|
|
||||||
|
private static final String ZERO_TO_255
|
||||||
|
= "(\\d{1,2}|(0|1)\\"
|
||||||
|
+ "d{2}|2[0-4]\\d|25[0-5])";
|
||||||
|
private static final String IP_ADDRESS_REGEX
|
||||||
|
= ZERO_TO_255 + "\\."
|
||||||
|
+ ZERO_TO_255 + "\\."
|
||||||
|
+ ZERO_TO_255 + "\\."
|
||||||
|
+ ZERO_TO_255;
|
||||||
|
|
||||||
|
private static final Pattern IP_ADDRESS_PATTERN = Pattern.compile("listening on (" + IP_ADDRESS_REGEX + "):" + PORT);
|
||||||
|
|
||||||
static final Set<Class<? extends Spi>> ALLOWED_SPIS = ImmutableSet.<Class<? extends Spi>>builder()
|
static final Set<Class<? extends Spi>> ALLOWED_SPIS = ImmutableSet.<Class<? extends Spi>>builder()
|
||||||
.add(HotRodConnectionSpi.class)
|
.add(HotRodConnectionSpi.class)
|
||||||
.build();
|
.build();
|
||||||
|
@ -69,10 +89,12 @@ public class HotRodMapStorage extends KeycloakModelParameters {
|
||||||
static final Set<Class<? extends ProviderFactory>> ALLOWED_FACTORIES = ImmutableSet.<Class<? extends ProviderFactory>>builder()
|
static final Set<Class<? extends ProviderFactory>> ALLOWED_FACTORIES = ImmutableSet.<Class<? extends ProviderFactory>>builder()
|
||||||
.add(HotRodMapStorageProviderFactory.class)
|
.add(HotRodMapStorageProviderFactory.class)
|
||||||
.add(HotRodConnectionProviderFactory.class)
|
.add(HotRodConnectionProviderFactory.class)
|
||||||
.add(ConcurrentHashMapStorageProviderFactory.class) // TODO: this should be removed when we have a HotRod implementation for each area
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private HotRodServerRule hotRodServerRule = new HotRodServerRule();
|
private final GenericContainer<?> hotRodContainer = new GenericContainer("quay.io/infinispan/server:" + System.getProperty("infinispan.version"))
|
||||||
|
.withEnv("USER", USERNAME)
|
||||||
|
.withEnv("PASS", PASSWORD)
|
||||||
|
.withNetworkMode("host");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateConfig(Config cf) {
|
public void updateConfig(Config cf) {
|
||||||
|
@ -99,19 +121,38 @@ public class HotRodMapStorage extends KeycloakModelParameters {
|
||||||
.config("dir", "${project.build.directory:target}")
|
.config("dir", "${project.build.directory:target}")
|
||||||
.config("keyType.single-use-objects", "string");
|
.config("keyType.single-use-objects", "string");
|
||||||
|
|
||||||
|
if (HOST == null && START_CONTAINER) {
|
||||||
|
Matcher matcher = IP_ADDRESS_PATTERN.matcher(hotRodContainer.getLogs());
|
||||||
|
if (!matcher.find()) {
|
||||||
|
LOG.errorf("Cannot find IP address of the infinispan server in log:\\n%s ", hotRodContainer.getLogs());
|
||||||
|
throw new IllegalStateException("Cannot find IP address of the Infinispan server. See test log for Infinispan container log.");
|
||||||
|
}
|
||||||
|
HOST = matcher.group(1);
|
||||||
|
}
|
||||||
|
|
||||||
cf.spi(HotRodConnectionSpi.NAME).provider(DefaultHotRodConnectionProviderFactory.PROVIDER_ID)
|
cf.spi(HotRodConnectionSpi.NAME).provider(DefaultHotRodConnectionProviderFactory.PROVIDER_ID)
|
||||||
.config("enableSecurity", "false")
|
.config("host", HOST)
|
||||||
.config("configureRemoteCaches", "false");
|
.config("port", PORT)
|
||||||
|
.config("username", USERNAME)
|
||||||
|
.config("password", PASSWORD)
|
||||||
|
.config("configureRemoteCaches", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeSuite(Config cf) {
|
public void beforeSuite(Config cf) {
|
||||||
hotRodServerRule.createHotRodMapStoreServer();
|
if (START_CONTAINER) {
|
||||||
|
hotRodContainer
|
||||||
|
.withStartupTimeout(Duration.ofMinutes(5))
|
||||||
|
.waitingFor(Wait.forLogMessage(".*Infinispan Server.*started in.*", 1))
|
||||||
|
.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statement classRule(Statement base, Description description) {
|
public void afterSuite() {
|
||||||
return hotRodServerRule.apply(base, description);
|
if (START_CONTAINER) {
|
||||||
|
hotRodContainer.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HotRodMapStorage() {
|
public HotRodMapStorage() {
|
||||||
|
|
|
@ -98,7 +98,6 @@ public class UserSessionConcurrencyTest extends KeycloakModelTest {
|
||||||
// This is basically the same as JpaMapKeycloakTransaction#read method is doing after calling lockUserSessionsForModification() method
|
// This is basically the same as JpaMapKeycloakTransaction#read method is doing after calling lockUserSessionsForModification() method
|
||||||
if (isHotRodStore) {
|
if (isHotRodStore) {
|
||||||
SYNC_USESSION.lock();
|
SYNC_USESSION.lock();
|
||||||
releaseLockOnTransactionCommit(session, SYNC_USESSION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UserSessionModel uSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSession(realm, uId));
|
UserSessionModel uSession = lockUserSessionsForModification(session, () -> session.sessions().getUserSession(realm, uId));
|
||||||
|
@ -110,6 +109,10 @@ public class UserSessionConcurrencyTest extends KeycloakModelTest {
|
||||||
|
|
||||||
cSession.setNote(OIDCLoginProtocol.STATE_PARAM, "state-" + n);
|
cSession.setNote(OIDCLoginProtocol.STATE_PARAM, "state-" + n);
|
||||||
|
|
||||||
|
if (isHotRodStore) {
|
||||||
|
releaseLockOnTransactionCommit(session, SYNC_USESSION);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue