fix: considering source ordinality with spi options (#43805)

closes: #43793

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins 2025-11-06 12:01:18 -05:00 committed by GitHub
parent 1d3a1b554b
commit 4a63fcffaf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 32 additions and 16 deletions

View File

@ -377,17 +377,17 @@ NOTE: Enabling XA transactions in a containerized environment does not fully sup
To setup the JPA migrationStrategy (manual/update/validate) you should setup JPA provider as follows:
.Setting the `migration-strategy` for the `quarkus` provider of the `connections-jpa` SPI
<@kc.start parameters="--spi-connections--jpa--quarkus-migration-strategy=manual"/>
<@kc.start parameters="--spi-connections-jpa--quarkus--migration-strategy=manual"/>
If you want to get a SQL file for DB initialization, too, you have to add this additional SPI initializeEmpty (true/false):
.Setting the `initialize-empty` for the `quarkus` provider of the `connections-jpa` SPI
<@kc.start parameters="--spi-connections--jpa--quarkus-initialize-empty=false"/>
<@kc.start parameters="--spi-connections-jpa--quarkus--initialize-empty=false"/>
In the same way the migrationExport to point to a specific file and location:
.Setting the `migration-export` for the `quarkus` provider of the `connections-jpa` SPI
<@kc.start parameters="--spi-connections--jpa--quarkus-migration-export=<path>/<file.sql>"/>
<@kc.start parameters="--spi-connections-jpa--quarkus--migration-export=<path>/<file.sql>"/>
For more information, check the link:{upgrading_guide_link}#_migrate_db[Migrating the database] documentation.

View File

@ -54,7 +54,7 @@ public final class Configuration {
public static boolean isUserModifiable(ConfigValue configValue) {
// This could check as low as SysPropConfigSource DEFAULT_ORDINAL, which is 400
// for now we won't validate these as it's not expected for the user to specify options via system properties
return configValue.getConfigSourceOrdinal() >= KeycloakPropertiesConfigSource.PROPERTIES_FILE_ORDINAL;
return configValue.getConfigSourceName() != null && configValue.getConfigSourceOrdinal() >= KeycloakPropertiesConfigSource.PROPERTIES_FILE_ORDINAL;
}
public static boolean isSet(Option<?> option) {

View File

@ -20,14 +20,16 @@ package org.keycloak.quarkus.runtime.configuration;
import static org.keycloak.quarkus.runtime.configuration.Configuration.OPTION_PART_SEPARATOR;
import static org.keycloak.quarkus.runtime.configuration.Configuration.toDashCase;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.ConfigValue;
import org.keycloak.Config;
import org.keycloak.Config.Scope;
import io.smallrye.config.SmallRyeConfig;
public class MicroProfileConfigProvider implements Config.ConfigProvider {
public static final String NS_KEYCLOAK = "kc";
@ -36,13 +38,13 @@ public class MicroProfileConfigProvider implements Config.ConfigProvider {
public static final String NS_QUARKUS = "quarkus";
public static final String NS_QUARKUS_PREFIX = "quarkus" + ".";
private final org.eclipse.microprofile.config.Config config;
private final SmallRyeConfig config;
public MicroProfileConfigProvider() {
this(ConfigProvider.getConfig());
this(Configuration.getConfig());
}
public MicroProfileConfigProvider(org.eclipse.microprofile.config.Config config) {
public MicroProfileConfigProvider(SmallRyeConfig config) {
this.config = config;
}
@ -137,8 +139,15 @@ public class MicroProfileConfigProvider implements Config.ConfigProvider {
return config.getOptionalValue(separatorPrefix.concat(key), clazz).orElse(defaultValue);
}
String dashCase = toDashCase(key);
return config.getOptionalValue(separatorPrefix.concat(dashCase), clazz)
.or(() -> config.getOptionalValue(prefix.concat(dashCase), clazz)).orElse(defaultValue);
String name = separatorPrefix.concat(dashCase);
String oldName = prefix.concat(dashCase);
ConfigValue value = config.getConfigValue(name);
ConfigValue oldValue = config.getConfigValue(oldName);
if (value.getValue() == null
|| (oldValue.getValue() != null && oldValue.getSourceOrdinal() > value.getSourceOrdinal())) {
value = oldValue;
}
return Optional.ofNullable(config.convert(value.getValue(), clazz)).orElse(defaultValue);
}
@Override

View File

@ -311,8 +311,8 @@ public class PropertyMapper<T> {
return configValue;
}
// by unsetting the ordinal this will not be seen as directly modified by the user
return configValue.from().withName(name).withValue(mappedValue).withRawValue(value).withConfigSourceOrdinal(0).build();
// by unsetting the name this will not be seen as directly modified by the user
return configValue.from().withName(name).withValue(mappedValue).withRawValue(value).withConfigSourceName(null).build();
}
private ConfigValue convertValue(ConfigValue configValue) {

View File

@ -77,9 +77,9 @@ quarkus.http.limits.max-header-size=65535
%dev.kc.http-enabled=true
%dev.kc.hostname-strict=false
%dev.kc.cache=local
%dev.kc.spi-theme--cache-themes=false
%dev.kc.spi-theme--cache-templates=false
%dev.kc.spi-theme--static-max-age=-1
%dev.kc.spi-theme--cache--themes=false
%dev.kc.spi-theme--cache--templates=false
%dev.kc.spi-theme--static--max-age=-1
# The default configuration when running import, export, bootstrap-admin
%nonserver.kc.http-enabled=true

View File

@ -86,6 +86,12 @@ public class ConfigurationTest extends AbstractConfigurationTest {
assertEquals("http://envvar.unittest", initConfig("hostname", "default").get("frontendUrl"));
}
@Test
public void testEnvVarPriorityOverPropertiesFileMixedSpiNamingConventions() {
putEnvVar("KC_SPI_HOSTNAME_OTHER_FRONTEND_URL", "http://envvar.unittest");
assertEquals("http://envvar.unittest", initConfig("hostname", "other").get("frontendUrl"));
}
@Test
public void testKeycloakConfPlaceholder() {
assertEquals("info", createConfig().getRawValue("kc.log-level"));

View File

@ -1,4 +1,5 @@
spi-hostname-default-frontend-url = ${keycloak.frontendUrl:http://filepropdefault.unittest}
spi-hostname--other--frontend-url = ${keycloak.frontendUrl:http://filepropdefault.unittest}
log-level=${SOME_LOG_LEVEL:info}
log-level-io.k8s=${SOME_CATEGORY_LOG_LEVEL}
KC_LOG_LEVEL_IO_QUARKUS=trace