8000 Removal of of cli options for the cache stacks by ruchikajha95 · Pull Request #54901 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 5 additions & 14 deletions docs/documentation/upgrading/topics/changes/changes-27_0_0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -597,22 +597,13 @@ The `invite-user` and `invite-existing-user` admin client overloads that do not

End of Life features have been previously deprecated and are removed in this release.

=== Deprecated cache stacks no longer supported
=== Cache stack CLI option removed
// https://github.com/keycloak/keycloak/issues/53461

The following cache transport stacks are no longer supported:

* `azure`
* `ec2`
* `google`
* `jdbc-ping-udp`
* `kubernetes`
* `tcp`
* `udp`

The `--cache-stack` CLI option has been completely removed.
The only supported transport stack is `jdbc-ping`, which uses TCP for transport and the database for node discovery.
Communication between nodes is encrypted using TLS by default.

Remove the `cache-stack` setting from your configuration to use the default `jdbc-ping` stack.
If your cache configuration XML explicitly selects another transport stack, remove that selection as well.
Remove any discovery settings specific to the previous stack, such as `jgroups.dns.query`.
If you were using the `--cache-stack` option in your configuration, remove it.
To use a custom JGroups stack, configure it directly in your cache configuration XML file using the `--cache-config-file` option.
Remove any discovery settings specific to previously deprecated stacks, such as `jgroups.dns.query`.
3 changes: 2 additions & 1 deletion docs/guides/observability/health.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ use the `metrics-enabled` option as follows:

<@kc.build parameters="--health-enabled=true --metrics-enabled=true"/>

The cluster health check is only available for clustered setups when the cache transport stack `jdbc-ping` is used.
The cluster health check is available for clustered setups using the default database-based node discovery.
It is not available for custom transport stacks that use a different discovery mechanism.

</@tmpl.guide>
11 changes: 5 additions & 6 deletions docs/guides/server/caching.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ The current distributed cache implementation is built on top of https://infinisp
== Enable distributed caching
When you start {project_name} in production mode, by using the `start` command, caching is enabled and all {project_name} nodes in your network are discovered.

By default, caches use the `jdbc-ping` stack which is based upon a TCP transport and uses the configured database to track nodes joining the cluster.
{project_name} allows you to either choose from a set of pre-defined default transport stacks, or to define your own custom stack, as you will see later in this {section}.
Cluster nodes communicate over TCP and use the configured database to discover other nodes.

To explicitly enable distributed infinispan caching, enter this command:

Expand Down Expand Up @@ -208,7 +207,7 @@ The following options allow you to identify the cluster and its nodes:
Cluster name::
Defines the name of the cluster.
Only nodes with the same cluster name can discover each other and form a cluster.
Because {project_name} uses the database for node discovery via `jdbc-ping` by default, clusters that share the same database but should remain separate will merge unless they have distinct cluster names.
Because {project_name} uses the database for node discovery, clusters that share the same database but should remain separate will merge unless they have distinct cluster names.
The default cluster name is `ISPN`.
+
Use `+--cache-embedded-cluster-name+` (or environment variable `+KC_CACHE_EMBEDDED_CLUSTER_NAME+`).
Expand Down Expand Up @@ -277,9 +276,9 @@ We recommend to set up anti-affinity rules and/or topology spread constraints to
== Transport stack

The transport stack ensures that {project_name} nodes in a cluster communicate in a reliable fashion.
The only supported transport stack is `jdbc-ping`, which uses TCP for transport and the database for node discovery via the JGroups `JDBC_PING2` protocol.
{project_name} uses TCP for transport and the database for node discovery.

Encryption using TLS is enabled by default for the TCP-based `jdbc-ping` transport stack.
Communication between nodes is encrypted using TLS by default.
No additional CLI options or modifications of the cache XML are required.

With TLS enabled, {project_name} auto-generates a self-signed RSA 2048 bit certificate to secure the connection and uses TLS 1.3 to secure the communication.
Expand Down Expand Up @@ -338,7 +337,7 @@ To restrict unauthorized access, always use a self-signed certificate for each {
== Network Ports

To ensure a healthy {project_name} clustering, some network ports need to be open.
The table below shows the TCP ports that need to be open for the `jdbc-ping` stack, and a description of the traffic that goes through it.
The table below shows the TCP ports required for cluster communication, and a description of the traffic that goes through them.

|===
|Port |Option| Property | Description
Expand Down
1 change: 0 additions & 1 deletion docs/guides/server/update-compatibility.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ Changing the value of one of the following CLI options triggers a recreate updat
| Option | Rationale
| `--cache` | The `ispn` and `local` configurations are mutually exclusive, changing from one to another will lead to data loss.
| `--cache-config-file` | Changing the configuration file could result in incompatible cache or transport configurations, resulting in clusters not forming as expected.
| `--cache-stack` | Changing stack will result in the cluster not forming during rolling update and will lead to data loss.
| `--cache-embedded-mtls-enabled` | Enabling/Disabling TLS will result in the cluster not forming during rolling update and will lead to data loss.
| `--cache-remote-host` | Connecting to a new remote cache will cause previously cached data to be lost.
| `--cache-remote-port` | Connecting to a new remote cache will cause previously cached data to be lost.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.keycloak.Config;
import org.keycloak.common.Profile;
Expand All @@ -29,7 +28,6 @@
import static org.keycloak.spi.infinispan.CacheEmbeddedConfigProviderSpi.SPI_NAME;
import static org.keycloak.spi.infinispan.impl.embedded.DefaultCacheEmbeddedConfigProviderFactory.CONFIG;
import static org.keycloak.spi.infinispan.impl.embedded.DefaultCacheEmbeddedConfigProviderFactory.PROVIDER_ID;
import static org.keycloak.spi.infinispan.impl.embedded.DefaultCacheEmbeddedConfigProviderFactory.STACK;

public class CachingEmbeddedMetadataProvider extends AbstractCompatibilityMetadataProvider {

Expand Down Expand Up @@ -63,10 +61,6 @@ public Map<String, String> customMeta() {
meta.put(CONFIG, sha256Of(Paths.get(config.get(CONFIG))));
return meta;
}
@Override
public Stream<String> configKeys() {
return Stream.of(STACK);
}

private void addInt(Map<String, String> meta, String configKey, int defaultValue) {
Optional.ofNullable(config.getInt(configKey, defaultValue))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ public class DefaultCacheEmbeddedConfigProviderFactory implements CacheEmbeddedC
public static final String CONFIG_MUTATE = "configMutate";
public static final String TRACING = "tracingEnabled";
private static final String HISTOGRAMS = "metricsHistogramsEnabled";
public static final String STACK = "stack";
public static final String NODE_NAME = "nodeName";
public static final String SITE_NAME = "siteName";
public static final String MACHINE_NAME = "machineName";
Expand Down
< 10BC8 td id="diff-8890859aaee48cb3cfcf1870c92d44ff871f901db19052e4a8aa36a38c91e3f9L395" data-line-number="395" class="blob-num blob-num-deletion js-linkable-line-number">
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,11 @@ public static void configureJGroups(Config.Scope config, ConfigurationBuilderHol
if (isLocal(holder)) {
return;
}
var stack = config.get(DefaultCacheEmbeddedConfigProviderFactory.STACK);
if (stack != null) {
transportOf(holder).stack(stack);
}
configureTransport(config);
var tracingEnabled = config.getBoolean(TRACING, false);
var fdSockEnabled = config.getBoolean(FD_SOCK_ENABLED_NAME, FD_SOCK_ENABLED_DEFAULT);
configureDiscovery(holder, session, tracingEnabled, fdSockEnabled);
configureTls(holder, session);
errorUnsupportedStack(holder);
}

/**
Expand Down Expand Up @@ -389,27 +384,6 @@ private static List<ProtocolConfiguration> getProtocolConfigurations(String tabl
return list;
}

private static void errorUnsupportedStack(ConfigurationBuilderHolder holder) {
var stackName = transportStackOf(holder).get();
switch (stackName) {
// Hard error on those exotic stacks that are no longer supported. The user should migrate to jdbc-ping or a custom stack.
case "jdbc-ping-udp":
throw new RuntimeException(String.format(
"Cache stack '%s' has been removed. Use 'jdbc-ping' or configure a custom stack. " +
"See https://www.keycloak.org/docs/latest/upgrading/index.html for migration instructions.",
stackName));
// Log an error for the other stacks that are no longer supported, but still allow them to be used as they are provided by Infinispan.
// The user should migrate to jdbc-ping or a custom stack.
case "azure":
case "ec2":
case "google":
case "tcp":
case "udp":
case "kubernetes":
logger.errorf("Stack '%s' is no longer supported. Use 'jdbc-ping' instead", stackName);
}
}

private static TransportConfigurationBuilder transportOf(ConfigurationBuilderHolder holder) {
return holder.getGlobalConfigurationBuilder().transport();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ public Job desired(KeycloakRealmImport primary, Context<KeycloakRealmImport> con

var cacheEnvVarName = getKeycloakOptionEnvVarName("cache");
var healthEnvVarName = getKeycloakOptionEnvVarName("health-enabled");
var cacheStackEnvVarName = getKeycloakOptionEnvVarName("cache-stack");
var toRemove = Set.of(cacheEnvVarName, healthEnvVarName, cacheStackEnvVarName);
var toRemove = Set.of(cacheEnvVarName, healthEnvVarName);
envvars.removeIf(e -> toRemove.contains(e.getName()));

// The Job should not connect to the cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,8 @@ public void testEnvVarConflict() {
.withNewSpec()
.addNewContainer()
.addNewEnv()
.withName("KC_CACHE_STACK")
.withValue("template_stack")
.withName("KC_CACHE_CONFIG_FILE")
.withValue("template_cache.xml")
.endEnv()
.addNewEnv()
.withName("KC_DB_URL_HOST")
Expand All @@ -365,7 +365,7 @@ public void testEnvVarConflict() {

// Act
var podTemplate = getDeployment(additionalPodTemplate, null,
s -> s.addNewAdditionalOption("cache.stack" 10BC8 , "additional_stack")
s -> s.addNewAdditionalOption("cache.config-file", "additional_cache.xml")
.addNewAdditionalOption("http.port", "additional_port").withNewDatabaseSpec().withHost("spec-host")
.endDatabaseSpec())
.getSpec().getTemplate();
Expand All @@ -377,7 +377,7 @@ public void testEnvVarConflict() {
return e1;
}));
// template spec takes the most priority for envs - only fields called out in the KeycloakDeployment warning are overriden by the rest of the spec
assertThat(envVarMap.get("KC_CACHE_STACK").getValue()).isEqualTo("template_stack");
assertThat(envVarMap.get("KC_CACHE_CONFIG_FILE").getValue()).isEqualTo("template_cache.xml");
assertThat(envVarMap.get("KC_DB_URL_HOST").getValue()).isEqualTo("template_host");
// the main spec takes priority over the additional options
assertThat(envVarMap.get("KC_HTTP_PORT").getValue()).isEqualTo("8080");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,6 @@ public enum Mechanism {
+ "By default in development mode, a 'local' cache disables clustering and is intended for development and testing purposes.")
.build();

public enum Stack {
jdbc_ping;

@Override
public String toString() {
return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, super.toString());
}
}

public static final Option<Stack> CACHE_STACK = new OptionBuilder<>("cache-stack", Stack.class)
.category(OptionCategory.CACHE)
.strictExpectedValues(false)
.description("Define the default stack to use for cluster communication and node discovery. Defaults to 'jdbc-ping' if not set.")
// Do not set a default value here as it would otherwise overwrite an explicit stack chosen in cache config XML
.build();

public static final Option<File> CACHE_CONFIG_FILE = new OptionBuilder<>(CACHE_CONFIG_FILE_PROPERTY, File.class)
.category(OptionCategory.CACHE)
.description("Defines the file from which cache configuration should be loaded from. "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ final class CachingPropertyMappers implements PropertyMapperGrouping {
private static final String MULTI_SITE_OR_EMBEDDED_REMOTE_FEATURE_SET = "feature '%s' or '%s' is set".formatted(Profile.Feature.MULTI_SITE.getKey(), Profile.Feature.CLUSTERLESS.getKey());
private static final String MULTI_SITE_FEATURE_SET = "feature '%s' or '%s' is set".formatted(Profile.Feature.MULTI_SITE.getKey(), Profile.Feature.CLUSTERLESS.getKey());

private static final String CACHE_STACK_SET_TO_ISPN = "'cache' type is set to '" + CachingOptions.Mechanism.ispn.name() + "'";
private static final String STATELESS_FEATURE_SET = "feature '%s' is set".formatted(Profile.Feature.STATELESS.getKey());

@Override
Expand All @@ -44,11 +43,6 @@ public List<PropertyMapper<?>> getPropertyMappers() {
: Optional.ofNullable(value).orElse(Mechanism.ispn.name()))
.paramLabel("type")
.build(),
fromOption(CachingOptions.CACHE_STACK)
.isEnabled(CachingPropertyMappers::cacheSetToInfinispan, CACHE_STACK_SET_TO_ISPN)
.to("kc.spi-cache--embedded--default-stack")
.paramLabel("stack")
.build(),
fromOption(CachingOptions.CACHE_CONFIG_FILE)
.mapFrom(CachingOptions.CACHE, (value, context) -> {
if (CachingOptions.Mechanism.local.name().equals(value)) {
Expand Down Expand Up @@ -77,7 +71,7 @@ public List<PropertyMapper<?>> getPropertyMappers() {
.build(),
fromOption(CachingOptions.CACHE_EMBEDDED_MTLS_ENABLED)
.to("kc.spi-jgroups-mtls--default--activated")
.isEnabled(CachingPropertyMappers::getDefaultMtlsEnabled, "a TCP based cache-stack is used")
.isEnabled(CachingPropertyMappers::getDefaultMtlsEnabled, "the embedded cache uses TCP transport")
.build(),
fromOption(CachingOptions.CACHE_EMBEDDED_MTLS_KEYSTORE.withRuntimeSpecificDefault(getConfPathValue("cache-mtls-keystore.p12")))
.paramLabel("file")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

import org.keycloak.common.Profile;
import org.keycloak.common.util.DurationConverter;
import org.keycloak.config.CachingOptions;
import org.keycloak.config.CachingOptions.Stack;
import org.keycloak.config.DatabaseOptions;
import org.keycloak.config.Option;
import org.keycloak.config.OptionsUtil;
Expand Down Expand Up @@ -51,7 +49,6 @@
import static org.keycloak.config.DatabaseOptions.DB_TLS_TRUST_STORE_PASSWORD;
import static org.keycloak.config.DatabaseOptions.DB_TLS_TRUST_STORE_TYPE;
import static org.keycloak.config.DatabaseOptions.DB_URL;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getOptionalKcValue;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
import static org.keycloak.quarkus.runtime.configuration.mappers.DatabasePropertyMappers.Datasources.appendDatasourceMappers;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption;
Expand Down Expand Up @@ -363,11 +360,8 @@ public void validateConfig(Picocli picocli) {
}

private static boolean isJdbcPingStack() {
if (!CachingPropertyMappers.cacheSetToInfinispan()) {
return false;
}
String stack = getOptionalKcValue(CachingOptions.CACHE_STACK).orElse(Stack.jdbc_ping.toString());
return Stack.jdbc_ping.toString().equals(stack);
// jdbc-ping is now the only supported stack, so just check if ispn cache is enabled
return CachingPropertyMappers.cacheSetToInfinispan();
}

public static boolean isPostgresqlTargetServerTypeEnabled() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2165,8 +2165,8 @@ public void failPoolMaxSizeTooLowForJdbcPing() {
}

@Test
public void failPoolMaxSizeTooLowForExplicitJdbcPingStack() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start", "--db=postgres", "--db-pool-max-size=3", "--cache=ispn", "--cache-stack=jdbc-ping");
public void failPoolMaxSizeTooLowForJdbcPingStack() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start", "--db=postgres", "--db-pool-max-size=3", "--cache=ispn");
assertError(nonRunningPicocli, "db-pool-max-size");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import static org.keycloak.infinispan.compatibility.CachingEmbeddedMetadataProvider.majorMinorOf;
import static org.keycloak.quarkus.runtime.configuration.compatibility.DatabaseCompatibilityMetadataProvider.UNSUPPORTED_CHANGES_HASH_KEY;
import static org.keycloak.spi.infinispan.impl.embedded.DefaultCacheEmbeddedConfigProviderFactory.CONFIG;
import static org.keycloak.spi.infinispan.impl.embedded.DefaultCacheEmbeddedConfigProviderFactory.STACK;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
Expand Down Expand Up @@ -98,7 +97,6 @@ public void testCompatible() throws IOException {

var cacheMeta = info.get(CacheEmbeddedConfigProviderSpi.SPI_NAME);
assertEquals(CONFIG_FILE_NOT_FOUND, cacheMeta.get(CONFIG));
assertNull(cacheMeta.get(STACK));

var jgroupsMeta = info.get(JGroupsCertificateProviderSpi.SPI_NAME);
assertEquals("true", jgroupsMeta.get(DefaultJGroupsCertificateProviderFactory.ENABLED));
Expand Down Expand Up @@ -221,22 +219,6 @@ public void testChangeCacheEmbeddedToRemote() throws IOException {
assertThat(result.getErrString(), containsString("[%1$s] Rolling Update is not available. '%1$s.version' is incompatible:".formatted(CacheEmbeddedConfigProviderSpi.SPI_NAME)));
}

@Test
public void testChangeCacheStack() throws IOException {
var jsonFile = createTempFile("compatible", ".json");
var result = pseudoLaunch(UpdateCompatibility.NAME, UpdateCompatibilityMetadata.NAME, UpdateCompatibilityMetadata.OUTPUT_OPTION_NAME, jsonFile.getAbsolutePath());
assertThat(result.getOutString(), containsString("Metadata:"));
assertEquals(0, result.exitCode);

var info = JsonSerialization.mapper.readValue(jsonFile, UpdateCompatibilityCheck.METADATA_TYPE_REF);
info.remove(FeatureCompatibilityMetadataProvider.ID);
assertEquals(defaultMeta(), info);

result = pseudoLaunch(UpdateCompatibility.NAME, UpdateCompatibilityCheck.NAME, UpdateCompatibilityCheck.INPUT_OPTION_NAME, jsonFile.getAbsolutePath(), "--cache-stack", "kubernetes");
assertEquals(CompatibilityResult.ExitCode.RECREATE.value(), result.exitCode);
assertThat(result.getErrString(), containsString("[%1$s] Rolling Update is not availa D0D7 ble. '%1$s.stack' is incompatible: null -> kubernetes".formatted(CacheEmbeddedConfigProviderSpi.SPI_NAME)));
}

@Test
public void testDatabaseTypeChanged() throws IOException {
var jsonFile = createTempFile("compatible", ".json");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,6 @@ public void testClusterConfig() {

ConfigArgsConfigSource.setCliArgs("");
Assert.assertEquals("cache-local.xml", cacheEmbeddedConfiguration().get(DefaultCacheEmbeddedConfigProviderFactory.CONFIG));

ConfigArgsConfigSource.setCliArgs("--cache-stack=foo");
Assert.assertEquals("foo", cacheEmbeddedConfiguration().get(DefaultCacheEmbeddedConfigProviderFactory.STACK));
}

@Test
Expand Down
Loading
Loading
0