Add JDBC_PING2 stacks for both TCP and UDP
Closes #34265 Signed-off-by: Ryan Emerson <remerson@redhat.com> Signed-off-by: Alexander Schwartz <aschwart@redhat.com> Co-authored-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
fd1dd49ade
commit
6eb870fcfc
12 changed files with 110 additions and 65 deletions
13
.github/workflows/ci.yml
vendored
13
.github/workflows/ci.yml
vendored
|
@ -601,7 +601,18 @@ jobs:
|
|||
echo "Tests: $TESTS"
|
||||
./mvnw test ${{ env.SUREFIRE_RETRY }} -Pauth-server-quarkus -Pdb-${{ matrix.db }} "-Dwebdriver.chrome.driver=$CHROMEWEBDRIVER/chromedriver" -Dtest=$TESTS -pl testsuite/integration-arquillian/tests/base 2>&1 | misc/log/trimmer.sh
|
||||
|
||||
- name: Run cluster JDBC_PING2 smoke test
|
||||
- name: Run cluster JDBC_PING2 UDP smoke test
|
||||
run: |
|
||||
./mvnw test ${{ env.SUREFIRE_RETRY }} \
|
||||
-Pauth-server-cluster-quarkus \
|
||||
-Pdb-${{ matrix.db }} \
|
||||
-Dtest=RealmInvalidationClusterTest \
|
||||
-Dsession.cache.owners=2 \
|
||||
-Dauth.server.quarkus.cluster.stack=jdbc-ping-udp \
|
||||
-pl testsuite/integration-arquillian/tests/base \
|
||||
2>&1 | misc/log/trimmer.sh
|
||||
|
||||
- name: Run cluster JDBC_PING2 TCP smoke test
|
||||
run: |
|
||||
./mvnw test ${{ env.SUREFIRE_RETRY }} \
|
||||
-Pauth-server-cluster-quarkus \
|
||||
|
|
|
@ -219,7 +219,7 @@ To apply a specific cache stack, enter this command:
|
|||
|
||||
<@kc.start parameters="--cache-stack=<stack>"/>
|
||||
|
||||
The default stack is set to `jdbc-ping` when distributed caches are enabled.
|
||||
The default stack is set to `jdbc-ping-udp` when distributed caches are enabled.
|
||||
|
||||
=== Available transport stacks
|
||||
|
||||
|
@ -231,7 +231,8 @@ The following table shows transport stacks that are available without any furthe
|
|||
|
||||
|`tcp`|TCP|MPING (uses UDP multicast).
|
||||
|`udp`|UDP|UDP multicast
|
||||
|`jdbc-ping`|UDP|JDBC_PING2
|
||||
|`jdbc-ping-udp`|UDP|JDBC_PING2
|
||||
|`jdbc-ping`|TCP|JDBC_PING2
|
||||
|===
|
||||
|
||||
|
||||
|
|
|
@ -46,16 +46,24 @@ public class CachingOptions {
|
|||
public enum Stack {
|
||||
tcp,
|
||||
udp,
|
||||
jdbc_ping,
|
||||
jdbc_ping_udp,
|
||||
kubernetes,
|
||||
ec2,
|
||||
azure,
|
||||
google
|
||||
google;
|
||||
|
||||
@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)
|
||||
.expectedValues(false)
|
||||
.description("Define the default stack to use for cluster communication and node discovery. This option only takes effect if 'cache' is set to 'ispn'. Default: udp.")
|
||||
.description("Define the default stack to use for cluster communication and node discovery.")
|
||||
.defaultValue(Stack.jdbc_ping_udp)
|
||||
.build();
|
||||
|
||||
public static final Option<File> CACHE_CONFIG_FILE = new OptionBuilder<>(CACHE_CONFIG_FILE_PROPERTY, File.class)
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.io.File;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import org.keycloak.config.CachingOptions;
|
||||
|
@ -19,6 +20,8 @@ final class CachingPropertyMappers {
|
|||
|
||||
private static final String REMOTE_HOST_SET = "remote host is set";
|
||||
|
||||
private static final String CACHE_STACK_SET_TO_ISPN = "'cache' type is set to '" + CachingOptions.Mechanism.ispn.name() + "'";
|
||||
|
||||
private CachingPropertyMappers() {
|
||||
}
|
||||
|
||||
|
@ -28,6 +31,7 @@ final class CachingPropertyMappers {
|
|||
.paramLabel("type")
|
||||
.build(),
|
||||
fromOption(CachingOptions.CACHE_STACK)
|
||||
.isEnabled(CachingPropertyMappers::cacheSetToInfinispan, CACHE_STACK_SET_TO_ISPN)
|
||||
.to("kc.spi-connections-infinispan-quarkus-stack")
|
||||
.paramLabel("stack")
|
||||
.build(),
|
||||
|
@ -101,6 +105,11 @@ final class CachingPropertyMappers {
|
|||
return getOptionalKcValue(CachingOptions.CACHE_REMOTE_HOST_PROPERTY).isPresent();
|
||||
}
|
||||
|
||||
private static boolean cacheSetToInfinispan() {
|
||||
Optional<String> cache = getOptionalKcValue(CachingOptions.CACHE);
|
||||
return cache.isPresent() && cache.get().equals(CachingOptions.Mechanism.ispn.name());
|
||||
}
|
||||
|
||||
private static String resolveConfigFile(String value, ConfigSourceInterceptorContext context) {
|
||||
String homeDir = Environment.getHomeDir();
|
||||
|
||||
|
|
|
@ -371,38 +371,7 @@ public class CacheManagerFactory {
|
|||
}
|
||||
|
||||
private void configureTransportStack(ConfigurationBuilderHolder builder, KeycloakSession keycloakSession) {
|
||||
String transportStack = Configuration.getRawValue("kc.cache-stack");
|
||||
|
||||
var jdbcStackName = "jdbc-ping";
|
||||
var transportConfig = builder.getGlobalConfigurationBuilder().transport();
|
||||
var stackXmlAttribute = transportConfig.defaultTransport().attributes().attribute(STACK);
|
||||
if (transportStack != null && !transportStack.isBlank() && !jdbcStackName.equals(transportStack)) {
|
||||
transportConfig.defaultTransport().stack(transportStack);
|
||||
} else if (!stackXmlAttribute.isModified() || jdbcStackName.equals(stackXmlAttribute.get())){
|
||||
EntityManager em = keycloakSession.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||
var tableName = JpaUtils.getTableNameForNativeQuery("JGROUPS_PING", em);
|
||||
var attributes = Map.of(
|
||||
// Leave initialize_sql blank as table is already created by Keycloak
|
||||
"initialize_sql", "",
|
||||
// Explicitly specify clear and select_all SQL to ensure "cluster_name" column is used, as the default
|
||||
// "cluster" cannot be used with Oracle DB as it's a reserved word.
|
||||
"clear_sql", String.format("DELETE from %s WHERE cluster_name=?", tableName),
|
||||
"delete_single_sql", String.format("DELETE from %s WHERE address=?", tableName),
|
||||
"insert_single_sql", String.format("INSERT INTO %s values (?, ?, ?, ?, ?)", tableName),
|
||||
"select_all_pingdata_sql", String.format("SELECT address, name, ip, coord FROM %s WHERE cluster_name=?", tableName),
|
||||
"remove_all_data_on_view_change", "true",
|
||||
"register_shutdown_hook", "false",
|
||||
"stack.combine", "REPLACE",
|
||||
"stack.position", "PING"
|
||||
);
|
||||
var stack = List.of(new ProtocolConfiguration(JDBC_PING2.class.getSimpleName(), attributes));
|
||||
builder.addJGroupsStack(new EmbeddedJGroupsChannelConfigurator(jdbcStackName, stack, null), "udp");
|
||||
|
||||
Supplier<DataSource> dataSourceSupplier = Arc.container().select(AgroalDataSource.class)::get;
|
||||
transportConfig.addProperty(JGroupsTransport.DATA_SOURCE, dataSourceSupplier);
|
||||
transportConfig.defaultTransport().stack(jdbcStackName);
|
||||
}
|
||||
|
||||
if (Configuration.isTrue(CachingOptions.CACHE_EMBEDDED_MTLS_ENABLED_PROPERTY)) {
|
||||
validateTlsAvailable(transportConfig.build());
|
||||
var tls = new TLS()
|
||||
|
@ -418,6 +387,49 @@ public class CacheManagerFactory {
|
|||
transportConfig.addProperty(JGroupsTransport.SOCKET_FACTORY, tls.createSocketFactory());
|
||||
logger.info("MTLS enabled for communications for embedded caches");
|
||||
}
|
||||
|
||||
String transportStack = Configuration.getRawValue("kc.cache-stack");
|
||||
if (transportStack != null && !transportStack.isBlank() && !isJdbcPingStack(transportStack)) {
|
||||
transportConfig.defaultTransport().stack(transportStack);
|
||||
return;
|
||||
}
|
||||
|
||||
var stackXmlAttribute = transportConfig.defaultTransport().attributes().attribute(STACK);
|
||||
// If the user has explicitly defined a transport stack that is not jdbc-ping or jdbc-ping-udp, return
|
||||
if (stackXmlAttribute.isModified() && !isJdbcPingStack(stackXmlAttribute.get()))
|
||||
return;
|
||||
|
||||
var stackName = transportStack != null ?
|
||||
transportStack :
|
||||
stackXmlAttribute.isModified() ? stackXmlAttribute.get() : "jdbc-ping-udp";
|
||||
var udp = stackName.endsWith("udp");
|
||||
|
||||
EntityManager em = keycloakSession.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||
var tableName = JpaUtils.getTableNameForNativeQuery("JGROUPS_PING", em);
|
||||
var attributes = Map.of(
|
||||
// Leave initialize_sql blank as table is already created by Keycloak
|
||||
"initialize_sql", "",
|
||||
// Explicitly specify clear and select_all SQL to ensure "cluster_name" column is used, as the default
|
||||
// "cluster" cannot be used with Oracle DB as it's a reserved word.
|
||||
"clear_sql", String.format("DELETE from %s WHERE cluster_name=?", tableName),
|
||||
"delete_single_sql", String.format("DELETE from %s WHERE address=?", tableName),
|
||||
"insert_single_sql", String.format("INSERT INTO %s values (?, ?, ?, ?, ?)", tableName),
|
||||
"select_all_pingdata_sql", String.format("SELECT address, name, ip, coord FROM %s WHERE cluster_name=?", tableName),
|
||||
"remove_all_data_on_view_change", "true",
|
||||
"register_shutdown_hook", "false",
|
||||
"stack.combine", "REPLACE",
|
||||
"stack.position", udp ? "PING" : "MPING"
|
||||
);
|
||||
var stack = List.of(new ProtocolConfiguration(JDBC_PING2.class.getSimpleName(), attributes));
|
||||
builder.addJGroupsStack(new EmbeddedJGroupsChannelConfigurator(stackName, stack, null), udp ? "udp" : "tcp");
|
||||
|
||||
Supplier<DataSource> dataSourceSupplier = Arc.container().select(AgroalDataSource.class)::get;
|
||||
transportConfig.addProperty(JGroupsTransport.DATA_SOURCE, dataSourceSupplier);
|
||||
transportConfig.defaultTransport().stack(stackName);
|
||||
}
|
||||
|
||||
private boolean isJdbcPingStack(String stackName) {
|
||||
return "jdbc-ping".equals(stackName) || "jdbc-ping-udp".equals(stackName);
|
||||
}
|
||||
|
||||
private static void validateTlsAvailable(GlobalConfiguration config) {
|
||||
|
|
|
@ -47,6 +47,15 @@ public class ClusterConfigDistTest {
|
|||
void changeClusterSetting(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertClusteredCache();
|
||||
assertThat(cliResult.getOutput(), Matchers.containsString("ISPN000078: Starting JGroups channel `ISPN` with stack `jdbc-ping-udp`"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "start-dev", "--cache=ispn", "--cache-stack=jdbc-ping"})
|
||||
void testJdbcPingTCP(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertClusteredCache();
|
||||
assertThat(cliResult.getOutput(), Matchers.containsString("ISPN000078: Starting JGroups channel `ISPN` with stack `jdbc-ping`"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -69,11 +69,6 @@ Cache:
|
|||
specified via XML file (see 'cache-config-file' option.). If the option is
|
||||
specified, 'cache-remote-username' and 'cache-remote-password' are required
|
||||
as well and the related configuration in XML file should not be present.
|
||||
--cache-stack <stack>
|
||||
Define the default stack to use for cluster communication and node discovery.
|
||||
This option only takes effect if 'cache' is set to 'ispn'. Default: udp.
|
||||
Possible values are: tcp, udp, kubernetes, ec2, azure, google, or a custom
|
||||
one.
|
||||
|
||||
Config:
|
||||
|
||||
|
|
|
@ -97,9 +97,9 @@ Cache:
|
|||
host is set.
|
||||
--cache-stack <stack>
|
||||
Define the default stack to use for cluster communication and node discovery.
|
||||
This option only takes effect if 'cache' is set to 'ispn'. Default: udp.
|
||||
Possible values are: tcp, udp, kubernetes, ec2, azure, google, or a custom
|
||||
one.
|
||||
Possible values are: tcp, udp, jdbc-ping, jdbc-ping-udp, kubernetes, ec2,
|
||||
azure, google, or a custom one. Default: jdbc-ping-udp. Available only when
|
||||
'cache' type is set to 'ispn'.
|
||||
|
||||
Config:
|
||||
|
||||
|
|
|
@ -72,9 +72,9 @@ Cache:
|
|||
as well and the related configuration in XML file should not be present.
|
||||
--cache-stack <stack>
|
||||
Define the default stack to use for cluster communication and node discovery.
|
||||
This option only takes effect if 'cache' is set to 'ispn'. Default: udp.
|
||||
Possible values are: tcp, udp, kubernetes, ec2, azure, google, or a custom
|
||||
one.
|
||||
Possible values are: tcp, udp, jdbc-ping, jdbc-ping-udp, kubernetes, ec2,
|
||||
azure, google, or a custom one. Default: jdbc-ping-udp. Available only when
|
||||
'cache' type is set to 'ispn'.
|
||||
|
||||
Config:
|
||||
|
||||
|
|
|
@ -98,9 +98,9 @@ Cache:
|
|||
host is set.
|
||||
--cache-stack <stack>
|
||||
Define the default stack to use for cluster communication and node discovery.
|
||||
This option only takes effect if 'cache' is set to 'ispn'. Default: udp.
|
||||
Possible values are: tcp, udp, kubernetes, ec2, azure, google, or a custom
|
||||
one.
|
||||
Possible values are: tcp, udp, jdbc-ping, jdbc-ping-udp, kubernetes, ec2,
|
||||
azure, google, or a custom one. Default: jdbc-ping-udp. Available only when
|
||||
'cache' type is set to 'ispn'.
|
||||
|
||||
Config:
|
||||
|
||||
|
|
|
@ -72,9 +72,9 @@ Cache:
|
|||
as well and the related configuration in XML file should not be present.
|
||||
--cache-stack <stack>
|
||||
Define the default stack to use for cluster communication and node discovery.
|
||||
This option only takes effect if 'cache' is set to 'ispn'. Default: udp.
|
||||
Possible values are: tcp, udp, kubernetes, ec2, azure, google, or a custom
|
||||
one.
|
||||
Possible values are: tcp, udp, jdbc-ping, jdbc-ping-udp, kubernetes, ec2,
|
||||
azure, google, or a custom one. Default: jdbc-ping-udp. Available only when
|
||||
'cache' type is set to 'ispn'.
|
||||
|
||||
Config:
|
||||
|
||||
|
|
|
@ -98,9 +98,9 @@ Cache:
|
|||
host is set.
|
||||
--cache-stack <stack>
|
||||
Define the default stack to use for cluster communication and node discovery.
|
||||
This option only takes effect if 'cache' is set to 'ispn'. Default: udp.
|
||||
Possible values are: tcp, udp, kubernetes, ec2, azure, google, or a custom
|
||||
one.
|
||||
Possible values are: tcp, udp, jdbc-ping, jdbc-ping-udp, kubernetes, ec2,
|
||||
azure, google, or a custom one. Default: jdbc-ping-udp. Available only when
|
||||
'cache' type is set to 'ispn'.
|
||||
|
||||
Config:
|
||||
|
||||
|
|
Loading…
Reference in a new issue