[fixes #9052] - Renaming cluster options to cache

This commit is contained in:
Pedro Igor 2021-12-09 12:19:14 -03:00 committed by Stian Thorgersen
parent 50060775f6
commit bf0f3d605c
14 changed files with 105 additions and 115 deletions

View file

@ -94,11 +94,7 @@
<filtered>true</filtered>
</file>
<file>
<source>target/keycloak-quarkus-server/cluster-local.xml</source>
<outputDirectory>conf</outputDirectory>
</file>
<file>
<source>target/keycloak-quarkus-server/cluster-default.xml</source>
<source>target/keycloak-quarkus-server/cache-ispn.xml</source>
<outputDirectory>conf</outputDirectory>
</file>
<file>

View file

@ -45,19 +45,10 @@ public class CLusteringBuildSteps {
@Record(ExecutionTime.RUNTIME_INIT)
@BuildStep
void configureInfinispan(KeycloakRecorder recorder, BuildProducer<SyntheticBeanBuildItem> syntheticBeanBuildItems, ShutdownContextBuildItem shutdownContext) {
String pathPrefix;
String homeDir = Environment.getHomeDir();
if (homeDir == null) {
pathPrefix = "";
} else {
pathPrefix = homeDir + "/conf/";
}
String configFile = getConfigValue("kc.spi.connections-infinispan.quarkus.config-file").getValue();
if (configFile != null) {
Path configPath = Paths.get(pathPrefix + configFile);
Path configPath = Paths.get(configFile);
String path;
if (configPath.toFile().exists()) {

View file

@ -139,7 +139,7 @@ public class KeycloakRecorder {
}
private void configureTransportStack(ConfigurationBuilderHolder builder) {
String transportStack = Configuration.getRawValue("kc.cluster-stack");
String transportStack = Configuration.getRawValue("kc.cache-stack");
if (transportStack != null) {
builder.getGlobalConfigurationBuilder().transport().defaultTransport()

View file

@ -1,6 +1,11 @@
package org.keycloak.quarkus.runtime.configuration.mappers;
import java.util.Arrays;
import java.util.function.BiFunction;
import org.keycloak.quarkus.runtime.Environment;
import io.smallrye.config.ConfigSourceInterceptorContext;
final class ClusteringPropertyMappers {
@ -9,24 +14,51 @@ final class ClusteringPropertyMappers {
public static PropertyMapper[] getClusteringPropertyMappers() {
return new PropertyMapper[] {
builder().from("cluster")
.to("kc.spi.connections-infinispan.quarkus.config-file")
.defaultValue("default")
.transformer((value, context) -> "cluster-" + value + ".xml")
.description("Specifies clustering configuration. The specified value points to the infinispan " +
"configuration file prefixed with the 'cluster-` inside the distribution configuration directory. " +
"Value 'local' effectively disables clustering and use infinispan caches in the local mode. " +
"Value 'default' enables clustering for infinispan caches.")
.paramLabel("mode")
builder().from("cache")
.defaultValue("ispn")
.description("Defines the cache mechanism for high-availability. "
+ "By default, a 'ispn' cache is used to create a cluster between multiple server nodes. "
+ "A 'local' cache disables clustering and is intended for development and testing purposes.")
.paramLabel("type")
.isBuildTimeProperty(true)
.expectedValues("local", "ispn")
.build(),
builder().from("cluster-stack")
builder().from("cache-stack")
.to("kc.spi.connections-infinispan.quarkus.stack")
.description("Define the default stack to use for cluster communication and node discovery.")
.description("Define the default stack to use for cluster communication and node discovery. This option only takes effect "
+ "if 'cache' is set to 'ispn'.")
.defaultValue("udp")
.paramLabel("stack")
.isBuildTimeProperty(true)
.expectedValues(Arrays.asList("tcp", "udp", "kubernetes", "ec2", "azure", "google"))
.build(),
builder().from("cache.config-file")
.mapFrom("cache")
.to("kc.spi.connections-infinispan.quarkus.config-file")
.description("Defines the file from which cache configuration should be loaded from.")
.transformer(new BiFunction<String, ConfigSourceInterceptorContext, String>() {
@Override
public String apply(String value, ConfigSourceInterceptorContext context) {
if ("local".equals(value)) {
return "cache-local.xml";
} else if ("ispn".equals(value)) {
return "cache-ispn.xml";
}
String pathPrefix;
String homeDir = Environment.getHomeDir();
if (homeDir == null) {
pathPrefix = "";
} else {
pathPrefix = homeDir + "/conf/";
}
return pathPrefix + value;
}
})
.paramLabel("file")
.isBuildTimeProperty(true)
.build()
};
}

View file

@ -101,6 +101,15 @@ public class PropertyMapper {
String parentKey = MicroProfileConfigProvider.NS_KEYCLOAK + "." + mapFrom;
ConfigValue parentValue = context.proceed(parentKey);
if (parentValue == null) {
// parent value not explicitly set, try to resolve the default value set to the parent property
PropertyMapper parentMapper = PropertyMappers.getMapper(parentKey);
if (parentMapper != null) {
parentValue = ConfigValue.builder().withValue(parentMapper.getDefaultValue()).build();
}
}
if (parentValue != null) {
ConfigValue value = transformValue(parentValue.getValue(), context);

View file

@ -28,7 +28,7 @@ metrics.enabled=false
%dev.http.enabled=true
%dev.hostname.strict=false
%dev.hostname.strict-https=false
%dev.cluster=local
%dev.cache=local
%dev.spi.theme.cache-themes=false
%dev.spi.theme.cache-templates=false
%dev.spi.theme.static-max-age=-1

View file

@ -313,17 +313,17 @@ public class ConfigurationTest {
@Test
public void testClusterConfig() {
// Cluster enabled by default, but disabled for the "dev" profile
Assert.assertEquals("cluster-default.xml", initConfig("connectionsInfinispan", "quarkus").get("configFile"));
Assert.assertEquals("cache-ispn.xml", initConfig("connectionsInfinispan", "quarkus").get("configFile"));
// If explicitly set, then it is always used regardless of the profile
System.clearProperty(Environment.PROFILE);
System.setProperty(CLI_ARGS, "--cluster=foo");
System.setProperty(CLI_ARGS, "--cache=cluster-foo.xml");
Assert.assertEquals("cluster-foo.xml", initConfig("connectionsInfinispan", "quarkus").get("configFile"));
System.setProperty(Environment.PROFILE, "dev");
Assert.assertEquals("cluster-foo.xml", initConfig("connectionsInfinispan", "quarkus").get("configFile"));
System.setProperty(CLI_ARGS, "--cluster-stack=foo");
System.setProperty(CLI_ARGS, "--cache-stack=foo");
Assert.assertEquals("foo", initConfig("connectionsInfinispan", "quarkus").get("stack"));
}

View file

@ -39,7 +39,7 @@ import io.quarkus.test.junit.main.LaunchResult;
public class BuildAndStartDistTest {
@Test
@Launch({ "build", "--http-enabled=true", "--hostname-strict=false", "--cluster=local" })
@Launch({ "build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(1)
void firstYouBuild(LaunchResult result) {
}

View file

@ -18,10 +18,12 @@
package org.keycloak.it.cli.dist;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.keycloak.it.cli.StartCommandTest;
import org.keycloak.it.junit5.extension.CLIResult;
import org.keycloak.it.junit5.extension.DistributionTest;
import io.quarkus.test.junit.main.Launch;
@ -31,26 +33,54 @@ import io.quarkus.test.junit.main.LaunchResult;
public class ClusterConfigDistTest {
@Test
@Launch({ "start-dev", "--cluster=default" })
@Launch({ "start-dev", "--cache=ispn" })
void changeClusterSetting(LaunchResult result) {
assertTrue(result.getOutput().contains("Received new cluster view"));
assertTrue(isClustered(result));
}
@Test
@Launch({ "start-dev", "--cluster=invalid" })
@Launch({ "build", "--cache-config-file=invalid" })
void failInvalidClusterConfig(LaunchResult result) {
assertTrue(result.getErrorOutput().contains("ERROR: Could not load cluster configuration file"));
}
@Test
@Launch({ "start-dev", "--cluster=default", "--cluster-stack=kubernetes" })
@Launch({ "start-dev", "--cache=ispn", "--cache-stack=kubernetes" })
void failMisConfiguredClusterStack(LaunchResult result) {
assertTrue(result.getOutput().contains("ERROR: dns_query can not be null or empty"));
}
@Test
@Launch({ "start-dev", "--cluster-stack=invalid" })
@Launch({ "build", "--cache-stack=invalid" })
void failInvalidClusterStack(LaunchResult result) {
assertTrue(result.getErrorOutput().contains("Invalid value for option '--cluster-stack': invalid. Expected values are: tcp, udp, kubernetes, ec2, azure, google"));
assertTrue(result.getErrorOutput().contains("Invalid value for option '--cache-stack': invalid. Expected values are: tcp, udp, kubernetes, ec2, azure, google"));
}
@Test
@Launch({ "start-dev", "--cache-config-file=cache-ispn.xml" })
void testExplicitCacheConfigFile(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertStartedDevMode();
assertTrue(isClustered(cliResult));
}
@Test
@Launch({ "start", "--http-enabled=true", "--hostname-strict false" })
void testStartDefaultsToClustering(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertStarted();
assertTrue(isClustered(result));
}
@Test
@Launch({ "start-dev" })
void testStartDevDefaultsToLocalCaches(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertStartedDevMode();
assertFalse(isClustered(result));
}
private boolean isClustered(LaunchResult result) {
return result.getOutput().contains("Received new cluster view");
}
}

View file

@ -44,9 +44,9 @@
</fileSets>
<files>
<file>
<source>src/main/content/conf/cluster-${auth.server.quarkus.cluster.config}.xml</source>
<source>src/main/content/conf/cluster-ha.xml</source>
<outputDirectory>/auth-server-quarkus/conf</outputDirectory>
<destName>cluster-${auth.server.quarkus.cluster.config}.xml</destName>
<destName>cluster-ha.xml</destName>
<filtered>true</filtered>
</file>
</files>

View file

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:11.0 http://www.infinispan.org/schemas/infinispan-config-11.0.xsd"
xmlns="urn:infinispan:config:11.0">
<!-- Local Cache Container Configuration -->
<cache-container name="keycloak">
<local-cache name="default">
<transaction transaction-manager-lookup="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup"/>
</local-cache>
<local-cache name="realms">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<memory storage="HEAP" max-count="10000"/>
</local-cache>
<local-cache name="users">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<memory storage="HEAP" max-count="10000"/>
</local-cache>
<local-cache name="sessions"/>
<local-cache name="authenticationSessions"/>
<local-cache name="offlineSessions"/>
<local-cache name="clientSessions"/>
<local-cache name="offlineClientSessions"/>
<local-cache name="loginFailures"/>
<local-cache name="work"/>
<local-cache name="authorization">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<memory storage="HEAP" max-count="10000"/>
</local-cache>
<local-cache name="keys">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<expiration max-idle="3600000"/>
<memory storage="HEAP" max-count="10000"/>
</local-cache>
<local-cache name="actionTokens">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<expiration max-idle="-1" interval="300000"/>
<memory storage="HEAP" max-count="-1"/>
</local-cache>
</cache-container>
</infinispan>

View file

@ -172,7 +172,13 @@ public class KeycloakQuarkusServerDeployableContainer implements DeployableConta
commands.add("-Djboss.node.name=" + configuration.getRoute());
}
commands.add("--cluster=" + System.getProperty("auth.server.quarkus.cluster.config", "local"));
String cacheMode = System.getProperty("auth.server.quarkus.cluster.config", "local");
if ("local".equals(cacheMode)) {
commands.add("--cache=local");
} else {
commands.add("--cache-config-file=cluster-" + cacheMode + ".xml");
}
commands.addAll(getAdditionalBuildArgs());
return commands.toArray(new String[0]);