Make quarkus runtime properties also available as runtime properties in keycloak

Changes behaviour to:
- all raw quarkus config properties are handled as runtime config in keycloak, with the exception of raw properties we need for additional datasources, there we check for build- vs runtime
- unknown quarkus buildtime properties require a build first or the usual quarkus warning is shown
- wrapped quarkus properties still get ignored / overwritten by our configuration layer (no change in behaviour here)

Closes #10968
This commit is contained in:
Dominik Guhr 2022-03-25 12:33:51 +01:00 committed by Pedro Igor
parent 66de8adefd
commit 9e57f836f2
13 changed files with 326 additions and 56 deletions

View file

@ -165,16 +165,19 @@ Once the first user with administrative rights exists, you can use the UI or the
== Unsupported server options
In most cases, the available options from the server configuration should suffice to configure the server.
However, you might need to use properties directly from Quarkus to enable a specific behavior or capability that is missing from the server configuration.
However, you might need to use properties directly from Quarkus to enable a specific behavior or capability that is missing in the keycloak configuration.
As much as possible, avoid using properties directly from Quarkus. If your need is essential, consider opening an https://github.com/keycloak/keycloak/issues/new?assignees=&labels=kind%2Fenhancement%2Cstatus%2Ftriage&template=enhancement.yml[issue] first and help us
to improve the server configuration.
To configure the server using Quarkus properties, perform the following steps:
If that's not possible for you, you can configure the server using Quarkus properties, perform the following steps:
. Create a `conf/quarkus.properties` file and define any property you need.
. Run the `build` command to apply the settings to the server
For a complete list of Quarkus properties, see the https://quarkus.io/guides/all-config[Quarkus documentation] .
When a raw quarkus property is a runtime property, it is also handled as runtime property for keycloak. When a quarkus property is a build time property, you have to invoke a new keycloak build first for the property to apply.
Note that some quarkus properties are mapped to internally by the Keycloak configuration, for example `quarkus.http.port` and similar properties that are needed to configure Keycloak. If the property is used by Keycloak, and you define the same property key in the quarkus.properties file, the keycloak configuration value takes precedence over the raw quarkus configuration value, so the value you set in `quarkus.properties` will be ignored when there is a value in the actual Keycloak configuration.
</@tmpl.guide>

View file

@ -34,6 +34,7 @@ import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIS
import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -42,8 +43,10 @@ import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.keycloak.quarkus.runtime.cli.command.Build;
import org.keycloak.quarkus.runtime.cli.command.ImportRealmMixin;
import org.keycloak.quarkus.runtime.cli.command.Main;
@ -51,6 +54,7 @@ import org.keycloak.quarkus.runtime.cli.command.Start;
import org.keycloak.quarkus.runtime.cli.command.StartDev;
import org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource;
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
import org.keycloak.quarkus.runtime.configuration.QuarkusPropertiesConfigSource;
import org.keycloak.quarkus.runtime.configuration.mappers.ConfigCategory;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
@ -65,9 +69,9 @@ import picocli.CommandLine.Model.ArgGroupSpec;
public final class Picocli {
public static final String ARG_PREFIX = "--";
private static final String ARG_KEY_VALUE_SEPARATOR = "=";
public static final String ARG_SHORT_PREFIX = "-";
public static final String NO_PARAM_LABEL = "none";
private static final String ARG_KEY_VALUE_SEPARATOR = "=";
private Picocli() {
}
@ -94,6 +98,7 @@ public final class Picocli {
private static int runReAugmentationIfNeeded(List<String> cliArgs, CommandLine cmd) {
int exitCode = 0;
if (hasAutoBuildOption(cliArgs) && !isHelpCommand(cliArgs)) {
if (cliArgs.contains(StartDev.NAME)) {
String profile = Environment.getProfile();
@ -269,9 +274,65 @@ public final class Picocli {
}
}
//check for defined quarkus raw build properties for UserStorageProvider extensions
if (QuarkusPropertiesConfigSource.getConfigurationFile() != null) {
Optional<ConfigSource> quarkusPropertiesConfigSource = getConfig().getConfigSource(QuarkusPropertiesConfigSource.NAME);
if (quarkusPropertiesConfigSource.isPresent()) {
Map<String, String> foundQuarkusBuildProperties = findSupportedRawQuarkusBuildProperties(quarkusPropertiesConfigSource.get().getProperties().entrySet());
//only check if buildProps are found in quarkus properties file.
if (!foundQuarkusBuildProperties.isEmpty()) {
Optional<ConfigSource> persistedConfigSource = getConfig().getConfigSource(PersistedConfigSource.NAME);
if(persistedConfigSource.isPresent()) {
for(String key : foundQuarkusBuildProperties.keySet()) {
if (notContainsKey(persistedConfigSource.get(), key)) {
//if persisted cs does not contain raw quarkus key from quarkus.properties, assume build is needed as the key is new.
return true;
}
}
//if it contains the key, check if the value actually changed from the persisted one.
return hasAtLeastOneChangedBuildProperty(foundQuarkusBuildProperties, persistedConfigSource.get().getProperties().entrySet());
}
}
}
}
return false;
}
private static boolean hasAtLeastOneChangedBuildProperty(Map<String, String> foundQuarkusBuildProperties, Set<Map.Entry<String, String>> persistedEntries) {
for(Map.Entry<String, String> persistedEntry : persistedEntries) {
if (foundQuarkusBuildProperties.containsKey(persistedEntry.getKey())) {
return isChangedValue(foundQuarkusBuildProperties, persistedEntry);
}
}
return false;
}
private static boolean notContainsKey(ConfigSource persistedConfigSource, String key) {
return !persistedConfigSource.getProperties().containsKey(key);
}
private static Map<String, String> findSupportedRawQuarkusBuildProperties(Set<Map.Entry<String, String>> entries) {
Pattern buildTimePattern = Pattern.compile(QuarkusPropertiesConfigSource.QUARKUS_DATASOURCE_BUILDTIME_REGEX);
Map<String, String> result = new HashMap<>();
for(Map.Entry<String, String> entry : entries) {
if (buildTimePattern.matcher(entry.getKey()).matches()) {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
}
private static boolean isChangedValue(Map<String, String> foundQuarkusBuildProps, Map.Entry<String, String> persistedEntry) {
return !foundQuarkusBuildProps.get(persistedEntry.getKey()).equals(persistedEntry.getValue());
}
private static boolean isProviderKey(String key) {
return key.startsWith("kc.provider.file");
}

View file

@ -49,11 +49,6 @@ public class PropertyMappingInterceptor implements ConfigSourceInterceptor {
return null;
}
if (isPersistedOnlyProperty(value)) {
// quarkus properties values always resolved from persisted config source
return value.withValue(PersistedConfigSource.getInstance().getValue(name));
}
if (value.getValue().indexOf("${") == -1) {
return value;
}
@ -70,19 +65,4 @@ public class PropertyMappingInterceptor implements ConfigSourceInterceptor {
return prop.getValue();
}));
}
private boolean isPersistedOnlyProperty(ConfigValue value) {
if (isQuarkusPropertiesEnabled && value.getName().startsWith(NS_QUARKUS)) {
String configSourceName = value.getConfigSourceName();
return Environment.isRuntimeMode()
&& configSourceName != null
&& !configSourceName.equals(PersistedConfigSource.NAME)
&& !configSourceName.equals(AbstractRawDefaultConfigSource.NAME)
&& !configSourceName.contains("Runtime Defaults")
&& !configSourceName.contains("application.properties");
}
return false;
}
}

View file

@ -45,9 +45,12 @@ import io.smallrye.config.common.utils.ConfigSourceUtil;
*/
public final class QuarkusPropertiesConfigSource extends AbstractLocationConfigSourceLoader implements ConfigSourceProvider {
private static final String NAME = "QuarkusProperties";
private static final String FILE_NAME = "quarkus.properties";
public static final String QUARKUS_PROPERTY_ENABLED = "kc.quarkus-properties-enabled";
public static final String NAME = "QuarkusProperties";
//for auto-build working with multiple datasources
public static final String QUARKUS_DATASOURCE_BUILDTIME_REGEX = "^quarkus\\.datasource\\.[A-Za-z0-9\\-_]+\\.(db-kind|jdbc\\.driver|jdbc\\.transactions|jdbc\\.enable-metrics)$";
public static boolean isSameSource(ConfigValue value) {
if (value == null) {
@ -91,13 +94,7 @@ public final class QuarkusPropertiesConfigSource extends AbstractLocationConfigS
@Override
public String getValue(String propertyName) {
if (propertyName.startsWith(NS_QUARKUS)) {
String value = super.getValue(propertyName);
if (value == null) {
return PersistedConfigSource.getInstance().getValue(propertyName);
}
return value;
return super.getValue(propertyName);
}
return null;
@ -111,13 +108,11 @@ public final class QuarkusPropertiesConfigSource extends AbstractLocationConfigS
configSources.addAll(loadConfigSources("META-INF/services/" + FILE_NAME, 450, classLoader));
if (Environment.isRebuild() || Environment.isRebuildCheck()) {
Path configFile = getConfigurationFile();
if (configFile != null) {
configSources.addAll(loadConfigSources(configFile.toUri().toString(), 500, classLoader));
}
}
return configSources;
}

View file

@ -1,5 +1,7 @@
package org.keycloak.quarkus.runtime.configuration.mappers;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.configuration.ConfigurationRuntimeConfig;
import io.smallrye.config.ConfigSourceInterceptorContext;
import io.smallrye.config.ConfigValue;
import org.keycloak.quarkus.runtime.Environment;
@ -53,14 +55,10 @@ public final class PropertyMappers {
}
public static boolean isBuildTimeProperty(String name) {
if (isFeaturesBuildTimeProperty(name) || isSpiBuildTimeProperty(name) || name.startsWith(MicroProfileConfigProvider.NS_QUARKUS_PREFIX)) {
if (isFeaturesBuildTimeProperty(name) || isSpiBuildTimeProperty(name)) {
return true;
}
if (!name.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX)) {
return false;
}
boolean isBuildTimeProperty = MAPPERS.entrySet().stream()
.anyMatch(new Predicate<Map.Entry<String, PropertyMapper>>() {
@Override

View file

@ -0,0 +1,24 @@
package org.keycloak.quarkus.runtime.configuration.test;
import org.junit.Test;
import org.keycloak.quarkus.runtime.configuration.QuarkusPropertiesConfigSource;
import java.util.regex.Pattern;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ConfigRegExPatternMatchingTest {
@Test
public void quarkusPropertyMultipleDatasourcePatternTest(){
Pattern p = Pattern.compile(QuarkusPropertiesConfigSource.QUARKUS_DATASOURCE_BUILDTIME_REGEX);
assertTrue(p.matcher("quarkus.datasource.user.jdbc.transactions").matches());
assertTrue(p.matcher("quarkus.datasource.user-store.jdbc.enable-metrics").matches());
assertTrue(p.matcher("quarkus.datasource.user12_store.db-kind").matches());
assertTrue(p.matcher("quarkus.datasource.user12_-__--store.db-kind").matches());
assertFalse(p.matcher("quarkus.datasource.user-store.db-username").matches());
assertFalse(p.matcher("quarkus.datasource.user-store.db-kin").matches());
}
}

View file

@ -93,6 +93,10 @@ public interface CLIResult extends LaunchResult {
assertFalse(getOutput().contains("Server configuration updated and persisted"));
}
default void assertBuildRuntimeMismatchWarning(String quarkusBuildtimePropKey) {
assertTrue(getOutput().contains(" - " + quarkusBuildtimePropKey + " is set to 'false' but it is build time fixed to 'true'. Did you change the property " + quarkusBuildtimePropKey + " after building the application?"));
}
default boolean isClustered() {
return getOutput().contains("Starting JGroups channel `ISPN`");
}

View file

@ -82,6 +82,8 @@ public class CLITestExtension extends QuarkusMainTestExtension {
}
if (distConfig != null) {
onKeepServerAlive(context.getRequiredTestMethod().getAnnotation(KeepServerAlive.class));
if (launch != null) {
if (dist == null) {
dist = createDistribution(distConfig);
@ -109,6 +111,16 @@ public class CLITestExtension extends QuarkusMainTestExtension {
}
}
private void onKeepServerAlive(KeepServerAlive annotation) {
if(annotation != null && dist != null) {
try {
dist.setManualStop(true);
} catch (Exception cause) {
throw new RuntimeException("Error when invoking " + annotation, cause);
}
}
}
@Override
public void afterEach(ExtensionContext context) throws Exception {
DistributionTest distConfig = getDistributionConfig(context);

View file

@ -0,0 +1,37 @@
/*
* 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.keycloak.it.utils.KeycloakDistribution;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.Consumer;
/**
* {@link KeepServerAlive} is used in a distributiontest to keep the server alive on test / method level.
* Used when when {@link DistributionTest} is invoked on class level not using keepAlive=true param, but
* for a specific test we need to run e.g. RestAssured verifications.
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface KeepServerAlive {
}

View file

@ -40,6 +40,10 @@ public interface KeycloakDistribution {
return commands.toArray(new String[0]);
}
default void setManualStop(boolean manualStop) {
throw new RuntimeException("Not implemented");
}
default void setQuarkusProperty(String key, String value) {
throw new RuntimeException("Not implemented");
}

View file

@ -322,6 +322,11 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
keycloak = builder.start();
}
@Override
public void setManualStop(boolean manualStop) {
this.manualStop = manualStop;
}
@Override
public void setProperty(String key, String value) {
setProperty(key, value, distPath.resolve("conf").resolve("keycloak.conf").toFile());

View file

@ -17,6 +17,7 @@
package org.keycloak.it.cli.dist;
import static io.restassured.RestAssured.when;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -35,7 +36,6 @@ import io.quarkus.test.junit.main.Launch;
import io.quarkus.test.junit.main.LaunchResult;
@DistributionTest(reInstall = DistributionTest.ReInstall.NEVER)
@BeforeStartDistribution(QuarkusPropertiesAutoBuildDistTest.UpdateConsoleLogLevelToWarn.class)
@RawDistOnly(reason = "Containers are immutable")
@TestMethodOrder(OrderAnnotation.class)
public class QuarkusPropertiesAutoBuildDistTest {
@ -43,16 +43,16 @@ public class QuarkusPropertiesAutoBuildDistTest {
@Test
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(1)
void testReAugOnFirstRun(LaunchResult result) {
void reAugOnFirstRun(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertBuild();
assertFalse(cliResult.getOutput().contains("INFO [io.quarkus]"));
}
@Test
@BeforeStartDistribution(QuarkusPropertiesAutoBuildDistTest.UpdateConsoleLogLevelToWarn.class)
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(2)
void testSecondStartDoNotTriggerReAug(LaunchResult result) {
void testQuarkusRuntimePropDoesNotTriggerReAug(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertNoBuild();
assertFalse(cliResult.getOutput().contains("INFO [io.quarkus]"));
@ -62,14 +62,60 @@ public class QuarkusPropertiesAutoBuildDistTest {
@BeforeStartDistribution(UpdateConsoleLogLevelToInfo.class)
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(3)
void testReAugAfterChangingProperty(LaunchResult result) {
void testNoReAugAfterChangingRuntimeProperty(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertBuild();
cliResult.assertNoBuild();
assertTrue(cliResult.getOutput().contains("INFO [io.quarkus]"));
}
public static class UpdateConsoleLogLevelToWarn implements Consumer<KeycloakDistribution> {
@Test
@BeforeStartDistribution(AddAdditionalDatasource.class)
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(4)
void testReAugForAdditionalDatasource(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertBuild();
}
@Test
@BeforeStartDistribution(ChangeAdditionalDatasourceUsername.class)
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(5)
void testNoReAugForAdditionalDatasourceRuntimeProperty(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertNoBuild();
}
@Test
@BeforeStartDistribution(ChangeAdditionalDatasourceDbKind.class)
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(6)
void testNoReAugWhenBuildTimePropertiesAreTheSame(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertNoBuild();
}
@Test
@BeforeStartDistribution(AddAdditionalDatasource2.class)
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(7)
void testReAugWhenAnotherDatasourceAdded(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertBuild();
}
@Test
@BeforeStartDistribution(EnableDatasourceMetrics.class)
@Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false", "--cache=local" })
@Order(8)
void testWrappedBuildPropertyTriggersBuildButGetsIgnoredWhenSetByQuarkus(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertBuild();
when().get("/metrics").then()
.statusCode(404);
}
public static class UpdateConsoleLogLevelToWarn implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.setQuarkusProperty("quarkus.log.console.level", "WARN");
@ -84,4 +130,44 @@ public class QuarkusPropertiesAutoBuildDistTest {
}
}
public static class AddAdditionalDatasource implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.setQuarkusProperty("quarkus.datasource.user-store.db-kind", "h2");
distribution.setQuarkusProperty("quarkus.datasource.user-store.username","sa");
distribution.setQuarkusProperty("quarkus.datasource.user-store.jdbc.url","jdbc:h2:mem:user-store;DB_CLOSE_DELAY=-1");
}
}
public static class AddAdditionalDatasource2 implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.setQuarkusProperty("quarkus.datasource.user-store2.db-kind", "h2");
distribution.setQuarkusProperty("quarkus.datasource.user-store2.db-transactions", "enabled");
distribution.setQuarkusProperty("quarkus.datasource.user-store2.username","sa");
distribution.setQuarkusProperty("quarkus.datasource.user-store2.jdbc.url","jdbc:h2:mem:user-store2;DB_CLOSE_DELAY=-1");
}
}
public static class ChangeAdditionalDatasourceUsername implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.setQuarkusProperty("quarkus.datasource.user-store.username","foo");
}
}
public static class ChangeAdditionalDatasourceDbKind implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.setQuarkusProperty("quarkus.datasource.user-store.db-kind","h2");
}
}
public static class EnableDatasourceMetrics implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.setManualStop(true);
distribution.setQuarkusProperty("quarkus.datasource.metrics.enabled","true");
}
}
}

View file

@ -17,6 +17,8 @@
package org.keycloak.it.cli.dist;
import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -28,6 +30,7 @@ import org.junit.jupiter.api.TestMethodOrder;
import org.keycloak.it.junit5.extension.BeforeStartDistribution;
import org.keycloak.it.junit5.extension.CLIResult;
import org.keycloak.it.junit5.extension.DistributionTest;
import org.keycloak.it.junit5.extension.KeepServerAlive;
import org.keycloak.it.junit5.extension.RawDistOnly;
import org.keycloak.it.utils.KeycloakDistribution;
@ -35,21 +38,23 @@ import io.quarkus.test.junit.main.Launch;
import io.quarkus.test.junit.main.LaunchResult;
@DistributionTest(reInstall = DistributionTest.ReInstall.NEVER)
@BeforeStartDistribution(QuarkusPropertiesDistTest.UpdateConsoleLogLevelToWarn.class)
@RawDistOnly(reason = "Containers are immutable")
@TestMethodOrder(OrderAnnotation.class)
public class QuarkusPropertiesDistTest {
private static final String QUARKUS_BUILDTIME_HIBERNATE_METRICS_KEY = "quarkus.hibernate-orm.metrics.enabled";
private static final String QUARKUS_RUNTIME_CONSOLE_LOGLVL_KEY = "quarkus.log.console.level";
@Test
@Launch({ "build", "--cache=local" })
@Order(1)
void testBuildWithPropertyFromQuarkusProperties(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
assertFalse(cliResult.getOutput().contains("INFO"));
cliResult.assertBuild();
}
@Test
@BeforeStartDistribution(QuarkusPropertiesDistTest.UpdateConsoleLogLevelToWarnFromQuarkusProps.class)
@Launch({ "start", "--http-enabled=true", "--hostname-strict=false" })
@Order(2)
void testPropertyEnabledAtRuntime(LaunchResult result) {
@ -75,7 +80,7 @@ public class QuarkusPropertiesDistTest {
}
@Test
@BeforeStartDistribution(UpdateConsoleLogLevelToInfo.class)
@BeforeStartDistribution(UpdateConsoleLogLevelToInfoFromKeycloakConf.class)
@Launch({ "build" })
@Order(5)
void testIgnoreQuarkusPropertyFromKeycloakConf(LaunchResult result) {
@ -84,20 +89,76 @@ public class QuarkusPropertiesDistTest {
cliResult.assertBuild();
}
public static class UpdateConsoleLogLevelToWarn implements Consumer<KeycloakDistribution> {
@Test
@BeforeStartDistribution(UpdateConsoleLogLevelToInfoFromQuarkusProps.class)
@Launch({ "start", "--http-enabled=true", "--hostname-strict=false" })
@Order(6)
void testRuntimePropFromQuarkusPropsIsAppliedWithoutRebuild(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
assertTrue(cliResult.getOutput().contains("INFO"));
cliResult.assertNoBuild();
}
@Test
@BeforeStartDistribution(UpdateHibernateMetricsFromQuarkusProps.class)
@Launch({ "start", "--http-enabled=true", "--hostname-strict=false" })
@Order(7)
void testBuildRunTimeMismatchOnQuarkusBuildPropWarning(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertBuildRuntimeMismatchWarning(QUARKUS_BUILDTIME_HIBERNATE_METRICS_KEY);
}
@Test
@BeforeStartDistribution(UpdateHibernateMetricsFromQuarkusProps.class)
@Launch({ "build", "--metrics-enabled=true" })
@Order(8)
void buildFirstWithUnknownQuarkusBuildProperty(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertBuild();
}
@Test
@KeepServerAlive
@Launch({ "start", "--http-enabled=true", "--hostname-strict=false" })
@Order(9)
void testUnknownQuarkusBuildTimePropertyApplied(LaunchResult result) {
CLIResult cliResult = (CLIResult) result;
cliResult.assertNoBuild();
when().get("/metrics").then().statusCode(200)
.body(containsString("vendor_hibernate_cache_query_plan_total"));
}
public static class UpdateConsoleLogLevelToWarnFromQuarkusProps implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.setQuarkusProperty("quarkus.log.console.level", "WARN");
distribution.setQuarkusProperty(QUARKUS_RUNTIME_CONSOLE_LOGLVL_KEY, "WARN");
}
}
public static class UpdateConsoleLogLevelToInfo implements Consumer<KeycloakDistribution> {
public static class UpdateConsoleLogLevelToInfoFromKeycloakConf implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.deleteQuarkusProperties();
distribution.setProperty("quarkus.log.console.level", "INFO");
distribution.setProperty(QUARKUS_RUNTIME_CONSOLE_LOGLVL_KEY, "INFO");
}
}
public static class UpdateConsoleLogLevelToInfoFromQuarkusProps implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.deleteQuarkusProperties();
distribution.setQuarkusProperty(QUARKUS_RUNTIME_CONSOLE_LOGLVL_KEY, "INFO");
}
}
public static class UpdateHibernateMetricsFromQuarkusProps implements Consumer<KeycloakDistribution> {
@Override
public void accept(KeycloakDistribution distribution) {
distribution.deleteQuarkusProperties();
distribution.setQuarkusProperty(QUARKUS_BUILDTIME_HIBERNATE_METRICS_KEY, "true");
}
}
}