diff --git a/model/map-hot-rod/pom.xml b/model/map-hot-rod/pom.xml
index 6939547577..a7ec96efd8 100644
--- a/model/map-hot-rod/pom.xml
+++ b/model/map-hot-rod/pom.xml
@@ -30,18 +30,6 @@
org.infinispan
infinispan-remote-query-client
-
- org.infinispan
- infinispan-server-router
-
-
- org.infinispan
- infinispan-server-rest
-
-
- org.infinispan
- infinispan-server-runtime
-
org.infinispan.protostream
protostream-processor
diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodUtils.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodUtils.java
index 739dbfc332..c1dd4f769f 100644
--- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodUtils.java
+++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodUtils.java
@@ -16,26 +16,7 @@
*/
package org.keycloak.models.map.storage.hotRod.common;
-import org.infinispan.manager.DefaultCacheManager;
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 Martin Kanis
@@ -44,51 +25,6 @@ public class HotRodUtils {
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> 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 Query paginateQuery(Query query, Integer first, Integer max) {
if (first != null && first > 0) {
query = query.startOffset(first);
diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/connections/DefaultHotRodConnectionProviderFactory.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/connections/DefaultHotRodConnectionProviderFactory.java
index 4832a6fb41..05172220aa 100644
--- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/connections/DefaultHotRodConnectionProviderFactory.java
+++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/connections/DefaultHotRodConnectionProviderFactory.java
@@ -30,7 +30,6 @@ import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
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.HotRodVersionUtils;
@@ -89,14 +88,10 @@ public class DefaultHotRodConnectionProviderFactory implements HotRodConnectionP
}
public void lazyInit() {
- if (config.getBoolean("embedded", false)) {
- HotRodUtils.createHotRodMapStoreServer(config.getInt("embeddedPort", 11444));
- }
-
ConfigurationBuilder remoteBuilder = new ConfigurationBuilder();
remoteBuilder.addServer()
.host(config.get("host", "localhost"))
- .port(config.getInt("port", 11444))
+ .port(config.getInt("port", 11222))
.clientIntelligence(ClientIntelligence.HASH_DISTRIBUTION_AWARE)
.marshaller(new ProtoStreamMarshaller());
diff --git a/pom.xml b/pom.xml
index 6090ad143f..0005681733 100644
--- a/pom.xml
+++ b/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
-->
2.3
+ 1.16.3
1.3.5
diff --git a/quarkus/runtime/pom.xml b/quarkus/runtime/pom.xml
index ea7da5fc5a..f8b21b6a74 100644
--- a/quarkus/runtime/pom.xml
+++ b/quarkus/runtime/pom.xml
@@ -469,28 +469,6 @@
-
- org.infinispan
- infinispan-server-rest
- ${infinispan.version}
-
-
- *
- *
-
-
-
-
- org.infinispan
- infinispan-server-router
- ${infinispan.version}
-
-
- *
- *
-
-
-
org.infinispan
infinispan-cachestore-remote
diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml
index 1b04f5a581..21f489c984 100644
--- a/testsuite/integration-arquillian/pom.xml
+++ b/testsuite/integration-arquillian/pom.xml
@@ -55,7 +55,6 @@
1.1.0.Final
1.0.0.Alpha2
1.6.1
- 1.5.1
6.1.0
diff --git a/testsuite/model/README.md b/testsuite/model/README.md
index c0cd5a2b71..f1012f5478 100644
--- a/testsuite/model/README.md
+++ b/testsuite/model/README.md
@@ -48,3 +48,59 @@ mvn test -Pjpa -Dtest=ClientModelTest \
```
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= \
+ -Dhot-rod.connection.port= \
+ -Dhot-rod.connection.username= \
+ -Dhot-rod.connection.password=
+```
diff --git a/testsuite/model/pom.xml b/testsuite/model/pom.xml
index e099eb258f..f573b55a37 100644
--- a/testsuite/model/pom.xml
+++ b/testsuite/model/pom.xml
@@ -120,6 +120,12 @@
postgresql
${postgresql.driver.version}
+
+ org.testcontainers
+ testcontainers
+ ${testcontainers.version}
+ test
+
@@ -171,7 +177,14 @@
${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase}
org.jboss.logmanager.LogManager
log4j
+ ${infinispan.version}
+
+
+ listener
+ org.keycloak.testsuite.model.AfterSuiteListener
+
+
diff --git a/testsuite/model/src/main/java/org/keycloak/testsuite/model/HotRodServerRule.java b/testsuite/model/src/main/java/org/keycloak/testsuite/model/HotRodServerRule.java
index 3ffb7579dd..64e55531ac 100644
--- a/testsuite/model/src/main/java/org/keycloak/testsuite/model/HotRodServerRule.java
+++ b/testsuite/model/src/main/java/org/keycloak/testsuite/model/HotRodServerRule.java
@@ -84,29 +84,6 @@ public class HotRodServerRule extends ExternalResource {
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) {
for (String c: cache) {
hotRodCacheManager.getCache(c, true);
diff --git a/testsuite/model/src/main/java/org/keycloak/testsuite/model/KeycloakModelParameters.java b/testsuite/model/src/main/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
index 5285642a68..5c0a137cb5 100644
--- a/testsuite/model/src/main/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
+++ b/testsuite/model/src/main/java/org/keycloak/testsuite/model/KeycloakModelParameters.java
@@ -72,4 +72,8 @@ public class KeycloakModelParameters {
public void beforeSuite(Config cf) {
}
+
+ public void afterSuite() {
+
+ }
}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/AfterSuiteListener.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/AfterSuiteListener.java
new file mode 100644
index 0000000000..30538d0dd1
--- /dev/null
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/AfterSuiteListener.java
@@ -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();
+ }
+ }
+}
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java
index b9b496847e..092231817a 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java
@@ -17,8 +17,7 @@
package org.keycloak.testsuite.model.parameters;
import com.google.common.collect.ImmutableSet;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
+import org.jboss.logging.Logger;
import org.keycloak.authorization.store.StoreFactorySpi;
import org.keycloak.events.EventStoreSpi;
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.client.MapClientProviderFactory;
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.singleUseObject.MapSingleUseObjectProviderFactory;
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.sessions.AuthenticationSessionSpi;
import org.keycloak.testsuite.model.Config;
-import org.keycloak.testsuite.model.HotRodServerRule;
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.regex.Matcher;
+import java.util.regex.Pattern;
/**
*
@@ -62,6 +64,24 @@ import java.util.Set;
*/
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> ALLOWED_SPIS = ImmutableSet.>builder()
.add(HotRodConnectionSpi.class)
.build();
@@ -69,10 +89,12 @@ public class HotRodMapStorage extends KeycloakModelParameters {
static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder()
.add(HotRodMapStorageProviderFactory.class)
.add(HotRodConnectionProviderFactory.class)
- .add(ConcurrentHashMapStorageProviderFactory.class) // TODO: this should be removed when we have a HotRod implementation for each area
.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
public void updateConfig(Config cf) {
@@ -99,19 +121,38 @@ public class HotRodMapStorage extends KeycloakModelParameters {
.config("dir", "${project.build.directory:target}")
.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)
- .config("enableSecurity", "false")
- .config("configureRemoteCaches", "false");
+ .config("host", HOST)
+ .config("port", PORT)
+ .config("username", USERNAME)
+ .config("password", PASSWORD)
+ .config("configureRemoteCaches", "true");
}
@Override
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
- public Statement classRule(Statement base, Description description) {
- return hotRodServerRule.apply(base, description);
+ public void afterSuite() {
+ if (START_CONTAINER) {
+ hotRodContainer.stop();
+ }
}
public HotRodMapStorage() {
diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java
index dc379a17cb..00a40352e2 100644
--- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java
+++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java
@@ -98,7 +98,6 @@ public class UserSessionConcurrencyTest extends KeycloakModelTest {
// This is basically the same as JpaMapKeycloakTransaction#read method is doing after calling lockUserSessionsForModification() method
if (isHotRodStore) {
SYNC_USESSION.lock();
- releaseLockOnTransactionCommit(session, SYNC_USESSION);
}
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);
+ if (isHotRodStore) {
+ releaseLockOnTransactionCommit(session, SYNC_USESSION);
+ }
+
return null;
}));