[KEYCLOAK-14255] - More improvements to CLI

This commit is contained in:
Pedro Igor 2020-09-22 17:34:07 -03:00
parent 76dede0f1e
commit 267be2d416
10 changed files with 326 additions and 192 deletions

View file

@ -1,7 +1,7 @@
# Default, and insecure, and non-production grade HTTP configuration
%dev.http.enabled=true
# Default Non-Production Grade Datasource
# Default and non-production grade database vendor
db=h2-file
db.username = sa
db.password = keycloak
# Default, and insecure, and non-production grade configuration for the development profile
%dev.http.enabled=true
%dev.db.username = sa
%dev.db.password = keycloak

View file

@ -151,7 +151,7 @@ class KeycloakProcessor {
}
}
recorder.setBuildTimeProperties(properties, Environment.isRebuild());
recorder.setBuildTimeProperties(properties, Environment.isRebuild(), KeycloakRecorder.getConfig().getRawValue("kc.config.args"));
recorder.showConfig();
}

View file

@ -0,0 +1,65 @@
/*
* Copyright 2020 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.cli;
import static org.keycloak.cli.Picocli.createCommandSpec;
import static org.keycloak.cli.Picocli.parseConfigArgs;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.keycloak.common.Version;
import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.annotations.QuarkusMain;
import picocli.CommandLine;
@QuarkusMain(name = "keycloak")
public class KeycloakMain {
public static void main(String args[]) {
System.setProperty("kc.version", Version.VERSION_KEYCLOAK);
if (args.length != 0) {
CommandLine cmd = new CommandLine(createCommandSpec());
List<String> argsList = new LinkedList<>(Arrays.asList(args));
try {
System.setProperty("kc.config.args", parseConfigArgs(argsList));
CommandLine.ParseResult result = cmd.parseArgs(argsList.toArray(new String[argsList.size()]));
if (!result.hasSubcommand() && (!result.isUsageHelpRequested() && !result.isVersionHelpRequested())) {
argsList.add(0, "start");
}
} catch (CommandLine.UnmatchedArgumentException e) {
if (!cmd.getParseResult().hasSubcommand()) {
argsList.add(0, "start");
} else {
cmd.getErr().println(e.getMessage());
System.exit(CommandLine.ExitCode.SOFTWARE);
}
}
System.exit(cmd.execute(argsList.toArray(new String[argsList.size()])));
}
Quarkus.run(args);
Quarkus.waitForExit();
}
}

View file

@ -1,132 +0,0 @@
/*
* Copyright 2020 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.cli;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;
import java.util.function.IntFunction;
import org.keycloak.common.Profile;
import org.keycloak.common.Version;
import org.keycloak.configuration.PropertyMapper;
import org.keycloak.configuration.PropertyMappers;
import org.keycloak.util.Environment;
import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.annotations.QuarkusMain;
import picocli.CommandLine;
@QuarkusMain(name = "keycloak")
public class KeycloakQuarkusMain {
public static void main(String args[]) {
System.setProperty("kc.version", Version.VERSION_KEYCLOAK);
if (args.length != 0) {
CommandLine.Model.CommandSpec spec = CommandLine.Model.CommandSpec.forAnnotatedObject(new MainCommand())
.name(Environment.getCommand());
addOption(spec, "start", PropertyMappers.getRuntimeMappers());
addOption(spec, "config", PropertyMappers.getRuntimeMappers());
addOption(spec, "config", PropertyMappers.getBuiltTimeMappers());
spec.subcommands().get("config").getCommandSpec().addOption(CommandLine.Model.OptionSpec.builder("--features")
.description("Enables a group of features. Possible values are: "
+ String.join(",", Arrays.asList(Profile.Type.values()).stream().map(
type -> type.name().toLowerCase()).toArray((IntFunction<CharSequence[]>) String[]::new)))
.type(String.class)
.build());
for (Profile.Feature feature : Profile.Feature.values()) {
spec.subcommands().get("config").getCommandSpec().addOption(CommandLine.Model.OptionSpec.builder("--features-" + feature.name().toLowerCase())
.description("Enables the " + feature.name() + " feature. Set enabled to enable the feature or disabled otherwise.")
.type(String.class)
.build());
}
CommandLine cmd = new CommandLine(spec);
List<String> argsList = new LinkedList<>(Arrays.asList(args));
if (argsList.isEmpty() || argsList.get(0).startsWith("--")) {
argsList.add(0, "start");
}
try {
System.setProperty("kc.config.args", parseConfigArgs(argsList));
cmd.parseArgs(argsList.toArray(new String[argsList.size()]));
} catch (CommandLine.UnmatchedArgumentException e) {
cmd.getErr().println(e.getMessage());
System.exit(CommandLine.ExitCode.SOFTWARE);
}
int exitCode = cmd.execute(argsList.toArray(new String[argsList.size()]));
if (exitCode != -1) {
System.exit(exitCode);
}
}
Quarkus.run(args);
Quarkus.waitForExit();
}
private static String parseConfigArgs(List<String> argsList) {
StringBuilder options = new StringBuilder();
Iterator<String> iterator = argsList.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
// TODO: ignore properties for providers for now, need to fetch them from the providers, otherwise CLI will complain about invalid options
if (key.startsWith("--spi")) {
iterator.remove();
}
if (key.startsWith("--")) {
if (options.length() > 0) {
options.append(",");
}
options.append(key);
}
}
return options.toString();
}
public static void addOption(CommandLine.Model.CommandSpec spec, String command, List<PropertyMapper> mappers) {
CommandLine.Model.CommandSpec commandSpec = spec.subcommands().get(command).getCommandSpec();
for (PropertyMapper mapper : mappers) {
String name = "--" + PropertyMappers.toCLIFormat(mapper.getFrom()).substring(3);
String description = mapper.getDescription();
if (description == null || commandSpec.optionsMap().containsKey(name)) {
continue;
}
CommandLine.Model.OptionSpec.Builder builder = CommandLine.Model.OptionSpec.builder(name).type(String.class);
builder.description(description);
commandSpec.addOption(builder.build());
}
}
}

View file

@ -17,22 +17,10 @@
package org.keycloak.cli;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.keycloak.configuration.KeycloakConfigSourceProvider;
import org.keycloak.configuration.MicroProfileConfigProvider;
import org.keycloak.quarkus.KeycloakRecorder;
import org.keycloak.util.Environment;
import io.quarkus.bootstrap.runner.QuarkusEntryPoint;
import io.quarkus.runtime.Quarkus;
import io.smallrye.config.ConfigValue;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Model.CommandSpec;
@ -44,8 +32,7 @@ import picocli.CommandLine.Spec;
header = "Keycloak - Open Source Identity and Access Management\n\nFind more information at: https://www.keycloak.org/%n",
description = "Use this command-line tool to manage your Keycloak cluster%n", footerHeading = "%nUse \"${COMMAND-NAME} <command> --help\" for more information about a command.%nUse \"${COMMAND-NAME} options\" for a list of all command-line options.",
footer = "%nby Red Hat",
parameterListHeading = "Server Options%n%n",
optionListHeading = "%nConfiguration Options%n%n",
optionListHeading = "Configuration Options%n%n",
commandListHeading = "%nCommands%n%n",
version = {
"Keycloak ${sys:kc.version}",
@ -63,23 +50,22 @@ public class MainCommand {
@Option(names = { "--version" }, versionHelp = true, hidden = true)
boolean version;
@CommandLine.Parameters(paramLabel = "server options", description = "Server options")
List<String> serverOptions;
@CommandLine.Parameters(paramLabel = "system properties", description = "Any Java system property you want set")
List<String> systemProperties;
@Option(names = "--profile", arity = "1", description = "Set the profile. Use 'dev' profile to enable development mode", scope = CommandLine.ScopeType.INHERIT)
@Option(names = "--profile", arity = "1", description = "Set the profile. Use 'dev' profile to enable development mode.", scope = CommandLine.ScopeType.INHERIT)
public void setProfile(String profile) {
System.setProperty("kc.profile", profile);
}
@Option(names = "--config-file", arity = "1", description = "Set the path to a configuration file", paramLabel = "<path>", scope = CommandLine.ScopeType.INHERIT)
@Option(names = "--config-file", arity = "1", description = "Set the path to a configuration file.", paramLabel = "<path>", scope = CommandLine.ScopeType.INHERIT)
public void setConfigFile(String path) {
System.setProperty(KeycloakConfigSourceProvider.KEYCLOAK_CONFIG_FILE_PROP, path);
}
@Command(name = "config", description = "Update the server configuration", mixinStandardHelpOptions = true, usageHelpAutoWidth = true)
@Command(name = "config",
description = "%nCreates a new server image based on the options passed to this command. Once created, configuration will be read from the server image and the server can be started without passing the same options again. Some configuration options require this command to be executed in order to actually change a configuration. For instance, the database vendor.%n",
mixinStandardHelpOptions = true,
usageHelpAutoWidth = true,
optionListHeading = "%nOptions%n",
parameterListHeading = "Available Commands%n")
public void reAugment() {
System.setProperty("quarkus.launch.rebuild", "true");
println("Updating the configuration and installing your custom providers, if any. Please wait.");
@ -92,16 +78,90 @@ public class MainCommand {
}
}
@Command(name = "start-dev", description = "Start the server in development mode", mixinStandardHelpOptions = true)
@Command(name = "start-dev",
description = "%nStart the server in development mode.%n",
mixinStandardHelpOptions = true,
optionListHeading = "%nOptions%n",
parameterListHeading = "Available Commands%n")
public void startDev() {
System.setProperty("kc.profile", "dev");
start();
}
@Command(name = "export",
description = "%nExport data from realms to a file or directory.%n",
mixinStandardHelpOptions = true,
showDefaultValues = true,
optionListHeading = "%nOptions%n",
parameterListHeading = "Available Commands%n")
public void runExport(@Option(names = "--dir", arity = "1", description = "Set the path to a directory where files will be created with the exported data.", paramLabel = "<path>") String toDir,
@Option(names = "--file", arity = "1", description = "Set the path to a file that will be created with the exported data.", paramLabel = "<path>") String toFile,
@Option(names = "--realm", arity = "1", description = "Set the name of the realm to export", paramLabel = "<realm>") String realm,
@Option(names = "--users", arity = "1", description = "Set how users should be exported. Possible values are: skip, realm_file, same_file, different_files.", paramLabel = "<strategy>", defaultValue = "different_files") String users,
@Option(names = "--users-per-file", arity = "1", description = "Set the number of users per file. Its used only if --users=different_files.", paramLabel = "<number>", defaultValue = "50") Integer usersPerFile) {
System.setProperty("keycloak.migration.action", "export");
if (toDir != null) {
System.setProperty("keycloak.migration.provider", "dir");
System.setProperty("keycloak.migration.dir", toDir);
} else if (toFile != null) {
System.setProperty("keycloak.migration.provider", "singleFile");
System.setProperty("keycloak.migration.file", toFile);
} else {
error("Must specify either --dir or --file options.");
}
System.setProperty("keycloak.migration.usersExportStrategy", users.toUpperCase());
if (usersPerFile != null) {
System.setProperty("keycloak.migration.usersPerFile", usersPerFile.toString());
}
if (realm != null) {
System.setProperty("keycloak.migration.realmName", realm);
}
start();
}
@Command(name = "import",
description = "%nImport data from a directory or a file.%n",
mixinStandardHelpOptions = true,
showDefaultValues = true,
optionListHeading = "%nOptions%n",
parameterListHeading = "Available Commands%n")
public void runImport(@Option(names = "--dir", arity = "1", description = "Set the path to a directory containing the files with the data to import", paramLabel = "<path>") String toDir,
@Option(names = "--file", arity = "1", description = "Set the path to a file with the data to import.", paramLabel = "<path>") String toFile,
@Option(names = "--realm", arity = "1", description = "Set the name of the realm to import", paramLabel = "<realm>") String realm,
@Option(names = "--override", arity = "1", description = "Set if existing data should be skipped or overridden.", paramLabel = "false", defaultValue = "true") boolean override) {
System.setProperty("keycloak.migration.action", "import");
if (toDir != null) {
System.setProperty("keycloak.migration.provider", "dir");
System.setProperty("keycloak.migration.dir", toDir);
} else if (toFile != null) {
System.setProperty("keycloak.migration.provider", "singleFile");
System.setProperty("keycloak.migration.file", toFile);
} else {
error("Must specify either --dir or --file options.");
}
if (realm != null) {
System.setProperty("keycloak.migration.realmName", realm);
}
System.setProperty("keycloak.migration.strategy", override ? "OVERWRITE_EXISTING" : "IGNORE_EXISTING");
start();
}
@Command(name = "start", description = "Start the server", mixinStandardHelpOptions = true, usageHelpAutoWidth = true)
@Command(name = "start",
description = "%nStart the server.%n",
mixinStandardHelpOptions = true,
usageHelpAutoWidth = true,
optionListHeading = "%nOptions%n",
parameterListHeading = "Available Commands%n")
public void start(
@CommandLine.Parameters(paramLabel = "show-config", arity = "0..1",
description = "Show all configuration options before starting the server") String showConfig) {
description = "Print out the configuration options when starting the server.") String showConfig) {
if (showConfig != null) {
System.setProperty("kc.show.config.runtime", Boolean.TRUE.toString());
System.setProperty("kc.show.config", "all");
@ -109,7 +169,11 @@ public class MainCommand {
start();
}
@Command(name = "show-config", description = "Print out the current configuration", mixinStandardHelpOptions = true)
@Command(name = "show-config",
description = "Print out the current configuration.",
mixinStandardHelpOptions = true,
optionListHeading = "%nOptions%n",
parameterListHeading = "Available Commands%n")
public void showConfiguration(
@CommandLine.Parameters(paramLabel = "filter", defaultValue = "none", description = "Show all configuration options. Use 'all' to show all options.") String filter) {
System.setProperty("kc.show.config", filter);

View file

@ -0,0 +1,95 @@
/*
* Copyright 2020 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.cli;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.IntFunction;
import org.keycloak.common.Profile;
import org.keycloak.configuration.PropertyMapper;
import org.keycloak.configuration.PropertyMappers;
import org.keycloak.util.Environment;
import picocli.CommandLine;
final class Picocli {
static CommandLine.Model.CommandSpec createCommandSpec() {
CommandLine.Model.CommandSpec spec = CommandLine.Model.CommandSpec.forAnnotatedObject(new MainCommand())
.name(Environment.getCommand());
addOption(spec, "start", PropertyMappers.getRuntimeMappers());
addOption(spec, "config", PropertyMappers.getRuntimeMappers());
addOption(spec, "config", PropertyMappers.getBuiltTimeMappers());
addOption(spec.subcommands().get("config").getCommandSpec(), "--features", "Enables a group of features. Possible values are: "
+ String.join(",", Arrays.asList(Profile.Type.values()).stream().map(
type -> type.name().toLowerCase()).toArray((IntFunction<CharSequence[]>) String[]::new)));
for (Profile.Feature feature : Profile.Feature.values()) {
addOption(spec.subcommands().get("config").getCommandSpec(), "--features-" + feature.name().toLowerCase(),
"Enables the " + feature.name() + " feature. Set enabled to enable the feature or disabled otherwise.");
}
return spec;
}
static String parseConfigArgs(List<String> argsList) {
StringBuilder options = new StringBuilder();
Iterator<String> iterator = argsList.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
// TODO: ignore properties for providers for now, need to fetch them from the providers, otherwise CLI will complain about invalid options
if (key.startsWith("--spi")) {
iterator.remove();
}
if (key.startsWith("--")) {
if (options.length() > 0) {
options.append(",");
}
options.append(key);
}
}
return options.toString();
}
private static void addOption(CommandLine.Model.CommandSpec spec, String command, List<PropertyMapper> mappers) {
CommandLine.Model.CommandSpec commandSpec = spec.subcommands().get(command).getCommandSpec();
for (PropertyMapper mapper : mappers) {
String name = "--" + PropertyMappers.toCLIFormat(mapper.getFrom()).substring(3);
String description = mapper.getDescription();
if (description == null || commandSpec.optionsMap().containsKey(name)) {
continue;
}
addOption(commandSpec, name, description);
}
}
private static void addOption(CommandLine.Model.CommandSpec commandSpec, String name, String description) {
commandSpec.addOption(CommandLine.Model.OptionSpec.builder(name)
.description(description)
.paramLabel("<value>")
.type(String.class).build());
}
}

View file

@ -148,8 +148,12 @@ public final class PropertyMappers {
}
public static String toCLIFormat(String name) {
if (name.indexOf('.') == -1) {
return name;
}
return MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX
.concat(name.substring(3).replaceAll("\\.", "-"));
.concat(name.substring(3, name.lastIndexOf('.') + 1)
.replaceAll("\\.", "-") + name.substring(name.lastIndexOf('.') + 1));
}
public static List<PropertyMapper> getRuntimeMappers() {

View file

@ -41,6 +41,7 @@ import javax.transaction.SystemException;
import javax.transaction.Transaction;
import com.fasterxml.jackson.core.type.TypeReference;
import io.quarkus.runtime.Quarkus;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.SessionImpl;
import org.jboss.logging.Logger;
@ -254,6 +255,7 @@ public class QuarkusJpaConnectionProviderFactory implements JpaConnectionProvide
if (exportImportManager.isRunExport()) {
exportImportManager.runExport();
Quarkus.asyncExit();
}
}
@ -395,6 +397,7 @@ public class QuarkusJpaConnectionProviderFactory implements JpaConnectionProvide
if (exportImportManager.isRunImport()) {
exportImportManager.runImport();
Quarkus.asyncExit();
} else {
importRealms();
}

View file

@ -20,10 +20,11 @@ package org.keycloak.quarkus;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import io.smallrye.config.ConfigValue;
import org.jboss.logging.Logger;
import org.keycloak.QuarkusKeycloakSessionFactory;
import org.keycloak.authentication.authenticators.directgrant.ValidateOTP;
import org.keycloak.cli.ShowConfigCommand;
import org.keycloak.common.Profile;
import org.keycloak.configuration.MicroProfileConfigProvider;
@ -39,23 +40,37 @@ import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigProviderResolver;
import liquibase.logging.LogFactory;
import liquibase.servicelocator.ServiceLocator;
import org.keycloak.util.Environment;
@Recorder
public class KeycloakRecorder {
private static final SmallRyeConfig CONFIG;
private static final Logger LOGGER = Logger.getLogger(KeycloakRecorder.class);
private static SmallRyeConfig CONFIG = null;
static {
CONFIG = (SmallRyeConfig) SmallRyeConfigProviderResolver.instance().getConfig();
}
private static Map<String, String> BUILD_TIME_PROPERTIES = Collections.emptyMap();
public static String getBuiltTimeProperty(String name) {
return BUILD_TIME_PROPERTIES.get(name);
String value = BUILD_TIME_PROPERTIES.get(name);
if (value == null) {
String profile = Environment.getProfile();
if (profile == null) {
profile = BUILD_TIME_PROPERTIES.get("kc.profile");
}
value = BUILD_TIME_PROPERTIES.get("%" + profile + "." + name);
}
return value;
}
public static SmallRyeConfig getConfig() {
if (CONFIG == null) {
CONFIG = (SmallRyeConfig) SmallRyeConfigProviderResolver.instance().getConfig();
}
return CONFIG;
}
@ -91,37 +106,57 @@ public class KeycloakRecorder {
QuarkusKeycloakSessionFactory.setInstance(new QuarkusKeycloakSessionFactory(factories, defaultProviders, reaugmented));
}
public void setBuildTimeProperties(Map<String, String> buildTimeProperties, Boolean rebuild) {
public void setBuildTimeProperties(Map<String, String> buildTimeProperties, Boolean rebuild, String configArgs) {
BUILD_TIME_PROPERTIES = buildTimeProperties;
String configHelpText = configArgs;
for (String propertyName : getConfig().getPropertyNames()) {
if (!propertyName.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX)) {
continue;
}
String buildValue = BUILD_TIME_PROPERTIES.get(propertyName);
String buildValue = Environment.getBuiltTimeProperty(propertyName).orElseGet(new Supplier<String>() {
@Override
public String get() {
return Environment.getBuiltTimeProperty(PropertyMappers.toCLIFormat(propertyName)).orElse(null);
}
});
ConfigValue value = getConfig().getConfigValue(propertyName);
if (PropertyMappers.isBuildTimeProperty(propertyName)) {
if (!rebuild && buildValue != null && value.getValue() != null && !buildValue.equalsIgnoreCase(value.getValue())) {
System.err.println("The value [" + value.getValue() + "] for property [" + propertyName + "] differs from the value [" + buildValue + "] set into the server image. Please, run the 'config' command to configure the server with the new value.");
System.exit(1);
}
if (!value.getConfigSourceName().contains("keycloak.properties")) {
System.err.println("The property [" + propertyName + "] can only be set when configuring the server. Please, run the 'config' command.");
System.exit(1);
}
}
if (buildValue != null && isRuntimeValue(value) && !buildValue.equalsIgnoreCase(value.getValue())) {
System.err.println("The value [" + value.getValue() + "] of property [" + propertyName + "] differs from the value [" + buildValue + "] set into the server image");
System.exit(1);
if (configHelpText != null) {
String currentProp = "--" + PropertyMappers.toCLIFormat(propertyName).substring(3) + "=" + buildValue;
String newProp = "--" + PropertyMappers.toCLIFormat(propertyName).substring(3) + "=" + value.getValue();
if (configHelpText.contains(currentProp)) {
LOGGER.warnf("The new value [%s] of the property [%s] in [%s] differs from the value [%s] set into the server image. The new value will override the value set into the server image.", value.getValue(), propertyName, value.getConfigSourceName(), buildValue);
configHelpText = configHelpText.replaceAll(currentProp, newProp);
} else if (!configHelpText.contains("--" + PropertyMappers.toCLIFormat(propertyName).substring(3))) {
configHelpText += newProp;
}
}
} else if (configHelpText != null && rebuild && isRuntimeValue(value)) {
String prop = "--" + PropertyMappers.toCLIFormat(propertyName).substring(3) + "=" + value.getValue();
if (!configHelpText.contains(prop)) {
LOGGER.infof("New property [%s] set with value [%s] in [%s]. This property is not persisted into the server image.",
propertyName, value.getValue(), value.getConfigSourceName(), buildValue);
configHelpText += " " + prop;
}
}
}
if (configArgs != null && !configArgs.equals(configHelpText)) {
LOGGER.infof("Please, run the 'config' command if you want to configure the server image with the new property values:\n\t%s config %s", Environment.getCommand(), String.join(" ", configHelpText.split(",")));
}
}
private boolean isRuntimeValue(ConfigValue value) {
return value.getValue() != null && !PropertyMappers.isBuildTimeProperty(value.getName());
String name = value.getName();
return value.getValue() != null && !PropertyMappers.isBuildTimeProperty(name)
&& !"kc.version".equals(name) && !"kc.config.args".equals(
name) && !"kc.home.dir".equals(name);
}
/**

View file

@ -52,13 +52,13 @@ public final class Environment {
if (profile == null) {
profile = System.getenv("KC_PROFILE");
}
return profile;
}
public static Optional<String> getBuiltTimeProperty(String name) {
String value = KeycloakRecorder.getBuiltTimeProperty(name);
if (value == null) {
return Optional.empty();
}