mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-06 14:59:55 -06:00
Add tests for lb-check endpoint
Added documentation why the check retries and updated outdated docs
Closes #25113
Signed-off-by: Michal Hajas <mhajas@redhat.com>
Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
Co-authored-by: Alexander Schwartz <aschwart@redhat.com>
(cherry picked from commit d387f13525)
Signed-off-by: Michal Hajas <mhajas@redhat.com>
Conflicts:
quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DatabaseContainer.java
This commit is contained in:
committed by
Alexander Schwartz
parent
ae4c7ebea9
commit
aecf36cd8c
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -185,7 +185,7 @@ jobs:
|
||||
PARAMS["sanity-check-zip"]="-Dtest=StartCommandDistTest,StartDevCommandDistTest,BuildAndStartDistTest,ImportAtStartupDistTest"
|
||||
PARAMS["zip"]=""
|
||||
PARAMS["container"]="-Dkc.quarkus.tests.dist=docker"
|
||||
PARAMS["storage"]="-Ptest-database -Dtest=PostgreSQLDistTest,MariaDBDistTest#testSuccessful,MySQLDistTest#testSuccessful,DatabaseOptionsDistTest,JPAStoreDistTest,HotRodStoreDistTest,MixedStoreDistTest,TransactionConfigurationDistTest"
|
||||
PARAMS["storage"]="-Ptest-database -Dtest=PostgreSQLDistTest,MariaDBDistTest#testSuccessful,MySQLDistTest#testSuccessful,DatabaseOptionsDistTest,JPAStoreDistTest,HotRodStoreDistTest,MixedStoreDistTest,TransactionConfigurationDistTest,ExternalInfinispanTest"
|
||||
|
||||
./mvnw install -pl quarkus/tests/integration -am -DskipTests
|
||||
./mvnw test -pl quarkus/tests/integration ${PARAMS["${{ matrix.server }}"]} | misc/log/trimmer.sh
|
||||
|
||||
@@ -62,13 +62,11 @@ Monitoring is necessary to detect degraded setups.
|
||||
|
||||
| {jdgserver_name} cluster failure
|
||||
| If the {jdgserver_name} cluster fails in the active site, {project_name} will not be able to communicate with the external {jdgserver_name}, and the {project_name} service will be unavailable.
|
||||
Manual switchover to the secondary site is recommended.
|
||||
Future versions will detect this situation and do an automatic failover.
|
||||
The loadbalancer will detect the situation as `/lb-check` returns an error, and will fail over to the other site.
|
||||
|
||||
When the {jdgserver_name} cluster is restored, its data will be out-of-sync with {project_name}.
|
||||
Manual operations are required to get {jdgserver_name} in the primary site in sync with the secondary site.
|
||||
| Loss of service
|
||||
| Human intervention required
|
||||
The setup is degraded until the {jdgserver_name} cluster is restored and the session data is re-synchronized to the primary.
|
||||
| No data loss^3^
|
||||
| Seconds to minutes (depending on load balancer setup)
|
||||
|
||||
| Connectivity {jdgserver_name}
|
||||
| If the connectivity between the two sites is lost, session information cannot be sent to the other site.
|
||||
|
||||
@@ -47,6 +47,8 @@ public class HealthDistTest {
|
||||
.statusCode(404);
|
||||
when().get("/q/health/ready").then()
|
||||
.statusCode(404);
|
||||
when().get("/lb-check").then()
|
||||
.statusCode(404);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -61,6 +63,8 @@ public class HealthDistTest {
|
||||
// Metrics should not be enabled
|
||||
when().get("/metrics").then()
|
||||
.statusCode(404);
|
||||
when().get("/lb-check").then()
|
||||
.statusCode(404);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -72,6 +76,8 @@ public class HealthDistTest {
|
||||
.statusCode(200)
|
||||
.body("checks[0].name", equalTo("Keycloak database connections health check"))
|
||||
.body("checks.size()", equalTo(1));
|
||||
when().get("/lb-check").then()
|
||||
.statusCode(404);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,6 +89,8 @@ public class HealthDistTest {
|
||||
.statusCode(200)
|
||||
.body("checks[0].name", equalTo("Keycloak database connections health check"))
|
||||
.body("checks.size()", equalTo(1));
|
||||
when().get("/lb-check").then()
|
||||
.statusCode(404);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -125,4 +133,11 @@ public class HealthDistTest {
|
||||
distribution.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--features=multi-site" })
|
||||
void testLoadBalancerCheck() {
|
||||
when().get("/lb-check").then()
|
||||
.statusCode(200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2021 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.it.storage.database;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.common.util.Retry;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.InfinispanContainer;
|
||||
import org.keycloak.it.junit5.extension.WithExternalInfinispan;
|
||||
|
||||
import static io.restassured.RestAssured.when;
|
||||
|
||||
@DistributionTest(keepAlive = true)
|
||||
@WithExternalInfinispan
|
||||
public class ExternalInfinispanTest {
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--features=multi-site", "--cache=ispn", "--cache-config-file=../../../test-classes/ExternalInfinispan/kcb-infinispan-cache-remote-store-config.xml", "-Djboss.site.name=ISPN" })
|
||||
void testLoadBalancerCheckFailure() {
|
||||
when().get("/lb-check").then()
|
||||
.statusCode(200);
|
||||
|
||||
InfinispanContainer.remoteCacheManager.administration().removeCache("sessions");
|
||||
|
||||
// The `lb-check` relies on the Infinispan's persistence check status. By default, Infinispan checks in the background every second that the remote store is available.
|
||||
// So we'll wait on average about one second here for the check to switch its state.
|
||||
Retry.execute(() -> {
|
||||
when().get("/lb-check").then()
|
||||
.statusCode(503);
|
||||
}, 10, 200);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- end::keycloak-ispn-configmap[] -->
|
||||
|
||||
<!--
|
||||
~ Copyright 2019 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.
|
||||
-->
|
||||
|
||||
<!--tag::keycloak-ispn-configmap[] -->
|
||||
<infinispan
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="urn:infinispan:config:14.0 https://www.infinispan.org/schemas/infinispan-config-14.0.xsd
|
||||
urn:infinispan:config:store:remote:14.0 https://www.infinispan.org/schemas/infinispan-cachestore-remote-config-14.0.xsd"
|
||||
xmlns="urn:infinispan:config:14.0">
|
||||
<!--end::keycloak-ispn-configmap[] -->
|
||||
|
||||
<!-- the statistics="true" attribute is not part of the original KC config and was added by Keycloak Benchmark -->
|
||||
<cache-container name="keycloak" statistics="true">
|
||||
<transport lock-timeout="60000"/>
|
||||
<metrics names-as-tags="true" />
|
||||
<local-cache name="realms" simple-cache="true" statistics="true">
|
||||
<encoding>
|
||||
<key media-type="application/x-java-object"/>
|
||||
<value media-type="application/x-java-object"/>
|
||||
</encoding>
|
||||
<memory max-count="10000"/>
|
||||
</local-cache>
|
||||
<local-cache name="users" simple-cache="true" statistics="true">
|
||||
<encoding>
|
||||
<key media-type="application/x-java-object"/>
|
||||
<value media-type="application/x-java-object"/>
|
||||
</encoding>
|
||||
<memory max-count="10000"/>
|
||||
</local-cache>
|
||||
<!--tag::keycloak-ispn-remotestore[] -->
|
||||
<distributed-cache name="sessions" owners="2" statistics="true">
|
||||
<expiration lifespan="-1"/>
|
||||
<persistence passivation="false"> <!--1-->
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="sessions"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/> <!--2-->
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/> <!--3-->
|
||||
</authentication>
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
<state-transfer enabled="false"/> <!--5-->
|
||||
</distributed-cache>
|
||||
<!--end::keycloak-ispn-remotestore[] -->
|
||||
<distributed-cache name="authenticationSessions" owners="2" statistics="true">
|
||||
<expiration lifespan="-1"/>
|
||||
<persistence passivation="false">
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="authenticationSessions"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/>
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/>
|
||||
</authentication>
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
<state-transfer enabled="false"/>
|
||||
</distributed-cache>
|
||||
<distributed-cache name="offlineSessions" owners="2" statistics="true">
|
||||
<expiration lifespan="-1"/>
|
||||
<persistence passivation="false">
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="offlineSessions"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/>
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/>
|
||||
</authentication>
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
<state-transfer enabled="false"/>
|
||||
</distributed-cache>
|
||||
<distributed-cache name="clientSessions" owners="2" statistics="true">
|
||||
<expiration lifespan="-1"/>
|
||||
<persistence passivation="false">
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="clientSessions"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/>
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/>
|
||||
</authentication>
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
<state-transfer enabled="false"/>
|
||||
</distributed-cache>
|
||||
<distributed-cache name="offlineClientSessions" owners="2" statistics="true">
|
||||
<expiration lifespan="-1"/>
|
||||
<persistence passivation="false">
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="offlineClientSessions"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/>
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/>
|
||||
</authentication>
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
<state-transfer enabled="false"/>
|
||||
</distributed-cache>
|
||||
<distributed-cache name="loginFailures" owners="2" statistics="true">
|
||||
<expiration lifespan="-1"/>
|
||||
<persistence passivation="false">
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="loginFailures"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/>
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/>
|
||||
</authentication>
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
<state-transfer enabled="false"/>
|
||||
</distributed-cache>
|
||||
<local-cache name="authorization" simple-cache="true" statistics="true">
|
||||
<encoding>
|
||||
<key media-type="application/x-java-object"/>
|
||||
<value media-type="application/x-java-object"/>
|
||||
</encoding>
|
||||
<memory max-count="10000"/>
|
||||
</local-cache>
|
||||
<replicated-cache name="work" statistics="true">
|
||||
<expiration lifespan="-1"/>
|
||||
<persistence passivation="false">
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="work"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/>
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/>
|
||||
</authentication>
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
|
||||
</replicated-cache>
|
||||
<local-cache name="keys" simple-cache="true" statistics="true">
|
||||
<encoding>
|
||||
<key media-type="application/x-java-object"/>
|
||||
<value media-type="application/x-java-object"/>
|
||||
</encoding>
|
||||
<expiration max-idle="3600000"/>
|
||||
<memory max-count="1000"/>
|
||||
</local-cache>
|
||||
<distributed-cache name="actionTokens" owners="2" statistics="true">
|
||||
<encoding>
|
||||
<key media-type="application/x-java-object"/>
|
||||
<value media-type="application/x-java-object"/>
|
||||
</encoding>
|
||||
<expiration max-idle="-1" lifespan="-1" interval="300000"/>
|
||||
<memory max-count="-1"/>
|
||||
<persistence passivation="false">
|
||||
<remote-store xmlns="urn:infinispan:config:store:remote:14.0"
|
||||
cache="actionTokens"
|
||||
raw-values="true"
|
||||
shared="true"
|
||||
segmented="false">
|
||||
<remote-server host="localhost"
|
||||
port="11222"/>
|
||||
<connection-pool max-active="16"
|
||||
exhausted-action="CREATE_NEW"/>
|
||||
<security>
|
||||
<authentication server-name="infinispan">
|
||||
<digest username="keycloak"
|
||||
password="Password1!"
|
||||
realm="default"/>
|
||||
</authentication>
|
||||
|
||||
</security>
|
||||
</remote-store>
|
||||
</persistence>
|
||||
<state-transfer enabled="false"/>
|
||||
</distributed-cache>
|
||||
</cache-container>
|
||||
</infinispan>
|
||||
@@ -35,8 +35,10 @@ import org.keycloak.quarkus.runtime.cli.command.StartDev;
|
||||
import org.keycloak.quarkus.runtime.configuration.KeycloakPropertiesConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.test.TestConfigArgsConfigSource;
|
||||
import org.keycloak.quarkus.runtime.integration.QuarkusPlatform;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -59,6 +61,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
||||
private KeycloakDistribution dist;
|
||||
private final Set<String> testSysProps = new HashSet<>();
|
||||
private DatabaseContainer databaseContainer;
|
||||
private InfinispanContainer infinispanContainer;
|
||||
private CLIResult result;
|
||||
|
||||
@Override
|
||||
@@ -88,6 +91,7 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
||||
}
|
||||
|
||||
configureDatabase(context);
|
||||
infinispanContainer = configureExternalInfinispan(context);
|
||||
|
||||
if (distConfig != null) {
|
||||
onKeepServerAlive(context.getRequiredTestMethod().getAnnotation(KeepServerAlive.class));
|
||||
@@ -192,6 +196,9 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
||||
databaseContainer.stop();
|
||||
databaseContainer = null;
|
||||
}
|
||||
if (infinispanContainer != null && infinispanContainer.isRunning()) {
|
||||
infinispanContainer.stop();
|
||||
}
|
||||
result = null;
|
||||
if (RAW.equals(DistributionType.getCurrent().orElse(RAW))) {
|
||||
if (distConfig != null && !DistributionTest.ReInstall.NEVER.equals(distConfig.reInstall()) && dist != null) {
|
||||
@@ -324,8 +331,24 @@ public class CLITestExtension extends QuarkusMainTestExtension {
|
||||
}
|
||||
}
|
||||
|
||||
private static InfinispanContainer configureExternalInfinispan(ExtensionContext context) {
|
||||
if (getAnnotationFromTestContext(context, WithExternalInfinispan.class) != null) {
|
||||
InfinispanContainer infinispanContainer = new InfinispanContainer();
|
||||
infinispanContainer.start();
|
||||
return infinispanContainer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static WithDatabase getDatabaseConfig(ExtensionContext context) {
|
||||
return context.getTestClass().orElse(Object.class).getDeclaredAnnotation(WithDatabase.class);
|
||||
return getAnnotationFromTestContext(context, WithDatabase.class);
|
||||
}
|
||||
|
||||
private static <T extends Annotation> T getAnnotationFromTestContext(ExtensionContext context, Class<T> annotationClass) {
|
||||
return context.getTestClass().map(c -> c.getDeclaredAnnotation(annotationClass))
|
||||
.or(() -> context.getTestMethod().map(m -> m.getAnnotation(annotationClass)))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private void configureDevServices() {
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2023 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.it.junit5.extension;
|
||||
|
||||
import org.infinispan.client.hotrod.RemoteCacheManager;
|
||||
import org.infinispan.client.hotrod.configuration.ClientIntelligence;
|
||||
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
|
||||
import org.infinispan.commons.configuration.XMLStringConfiguration;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
import org.testcontainers.images.PullPolicy;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class InfinispanContainer extends GenericContainer<InfinispanContainer> {
|
||||
|
||||
private final Logger LOG = Logger.getLogger(getClass());
|
||||
public static final String PORT = System.getProperty("keycloak.externalInfinispan.port", "11222");
|
||||
public static final String USERNAME = System.getProperty("keycloak.externalInfinispan.username", "keycloak");
|
||||
public static final String PASSWORD = System.getProperty("keycloak.externalInfinispan.password", DatabaseContainer.DEFAULT_PASSWORD);
|
||||
|
||||
public static RemoteCacheManager remoteCacheManager;
|
||||
|
||||
public InfinispanContainer() {
|
||||
super(getImageName());
|
||||
withEnv("USER", USERNAME);
|
||||
withEnv("PASS", PASSWORD);
|
||||
withNetworkMode("host");
|
||||
|
||||
// the images in the 'infinispan-test' repository point to tags that are frequently refreshed, therefore, always pull them
|
||||
if (getImageName().startsWith("quay.io/infinispan-test")) {
|
||||
withImagePullPolicy(PullPolicy.alwaysPull());
|
||||
}
|
||||
|
||||
|
||||
//order of waitingFor and withStartupTimeout matters as the latter sets the timeout for WaitStrategy set by waitingFor
|
||||
waitingFor(Wait.forLogMessage(".*Infinispan Server.*started in.*", 1));
|
||||
withStartupTimeout(Duration.ofMinutes(5));
|
||||
}
|
||||
|
||||
private static String getImageName() {
|
||||
String INFINISPAN_IMAGE = System.getProperty("kc.infinispan.container.image");
|
||||
if (INFINISPAN_IMAGE.matches("quay.io/infinispan/.*-SNAPSHOT")) {
|
||||
// If the image name ends with SNAPSHOT, someone is trying to use a snapshot release of Infinispan.
|
||||
// Then switch to the closest match of the Infinispan test container
|
||||
INFINISPAN_IMAGE = INFINISPAN_IMAGE.replaceAll("quay.io/infinispan/", "quay.io/infinispan-test/");
|
||||
INFINISPAN_IMAGE = INFINISPAN_IMAGE.replaceAll("[0-9]*-SNAPSHOT$", "x");
|
||||
}
|
||||
|
||||
return INFINISPAN_IMAGE;
|
||||
}
|
||||
|
||||
private void establishHotRodConnection() {
|
||||
ConfigurationBuilder configBuilder = new ConfigurationBuilder()
|
||||
.addServers(getContainerIpAddress() + ":11222")
|
||||
.security()
|
||||
.authentication()
|
||||
.username(getUsername())
|
||||
.password(getPassword())
|
||||
.clientIntelligence(ClientIntelligence.BASIC);
|
||||
|
||||
configBuilder.statistics().enable()
|
||||
.statistics().jmxEnable();
|
||||
|
||||
remoteCacheManager = new RemoteCacheManager(configBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
|
||||
establishHotRodConnection();
|
||||
|
||||
Stream.of("sessions", "actionTokens", "authenticationSessions", "clientSessions", "offlineSessions", "offlineClientSessions", "loginFailures", "work")
|
||||
.forEach(cacheName -> {
|
||||
LOG.infof("Creating cache '%s'", cacheName);
|
||||
createCache(remoteCacheManager, cacheName);
|
||||
});
|
||||
}
|
||||
|
||||
public void createCache(RemoteCacheManager remoteCacheManager, String cacheName) {
|
||||
String xml = String.format("<distributed-cache name=\"%s\" mode=\"SYNC\" owners=\"2\"></distributed-cache>" , cacheName);
|
||||
remoteCacheManager.administration().getOrCreateCache(cacheName, new XMLStringConfiguration(xml));
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return PORT;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return USERNAME;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return PASSWORD;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2021 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.it.junit5.extension;
|
||||
|
||||
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* {@link WithExternalInfinispan} is used to start an Infinispan container.
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@EnabledIfSystemProperty(named = "kc.test.storage.database", matches = "true", disabledReason = "Docker takes too much time and stability depends on the environment. We should try running these tests in CI but isolated.")
|
||||
public @interface WithExternalInfinispan {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user