fix: rationalizing cli using hidden options vs hard errors (#43945)

closes: #43940

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins 2025-11-27 05:43:08 -05:00 committed by GitHub
parent 39d1fa2825
commit f7a0bb7cbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 197 additions and 686 deletions

View File

@ -23,6 +23,7 @@ import java.util.Iterator;
import java.util.List;
import org.keycloak.config.OptionCategory;
import org.keycloak.quarkus.runtime.cli.command.AbstractCommand;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
import org.keycloak.utils.StringUtil;
@ -31,7 +32,6 @@ import picocli.CommandLine;
import picocli.CommandLine.Model.ArgGroupSpec;
import picocli.CommandLine.Model.OptionSpec;
import static org.keycloak.quarkus.runtime.cli.OptionRenderer.undecorateDuplicitOptionName;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.getMapper;
import static org.keycloak.utils.StringUtil.removeSuffix;
@ -44,10 +44,14 @@ public final class Help extends CommandLine.Help {
private static final int HELP_WIDTH = 100;
private static final String DEFAULT_OPTION_LIST_HEADING = "Options:";
private static final String DEFAULT_COMMAND_LIST_HEADING = "Commands:";
private static boolean ALL_OPTIONS;
private boolean all;
Help(CommandLine.Model.CommandSpec commandSpec, ColorScheme colorScheme) {
super(commandSpec, colorScheme);
if (commandSpec.userObject() instanceof AbstractCommand ac) {
all = ac.isHelpAll();
}
configureUsageMessage(commandSpec);
}
@ -163,11 +167,11 @@ public final class Help extends CommandLine.Help {
return false;
}
if (ALL_OPTIONS) {
if (all) {
return true;
}
String optionName = undecorateDuplicitOptionName(option.longestName());
String optionName = option.longestName();
OptionCategory category = null;
if (option.group() != null && option.group().heading() != null) {
@ -190,7 +194,4 @@ public final class Help extends CommandLine.Help {
return PropertyMappers.isSupported(mapper);
}
public static void setAllOptions(boolean allOptions) {
ALL_OPTIONS = allOptions;
}
}

View File

@ -26,7 +26,6 @@ import picocli.CommandLine.Help.IParamLabelRenderer;
import picocli.CommandLine.Model.OptionSpec;
import static org.keycloak.quarkus.runtime.cli.Picocli.NO_PARAM_LABEL;
import static org.keycloak.utils.StringUtil.removeSuffix;
import static picocli.CommandLine.Help.Ansi.OFF;
@ -34,7 +33,6 @@ public class OptionRenderer implements CommandLine.Help.IOptionRenderer {
private static final String OPTION_NAME_SEPARATOR = ", ";
private static final Text EMPTY_TEXT = OFF.text("");
public static final String DUPLICIT_OPTION_SUFFIX = " "; // works good (not perfect) for alphabetical sorting with non-duplicit options
@Override
public Text[][] render(OptionSpec option, IParamLabelRenderer paramLabelRenderer, ColorScheme scheme) {
@ -65,7 +63,8 @@ public class OptionRenderer implements CommandLine.Help.IOptionRenderer {
}
private Text createLongName(OptionSpec option, ColorScheme scheme) {
Text name = scheme.optionText(undecorateDuplicitOptionName(option.longestName()));
String longestName = option.longestName();
Text name = scheme.optionText(longestName);
String paramLabel = formatParamLabel(option);
if (StringUtil.isNotBlank(paramLabel) && !NO_PARAM_LABEL.equals(paramLabel) && !option.usageHelp() && !option.versionHelp()) {
@ -85,11 +84,4 @@ public class OptionRenderer implements CommandLine.Help.IOptionRenderer {
return "<" + label + ">";
}
public static String decorateDuplicitOptionName(String name) {
return name + DUPLICIT_OPTION_SUFFIX;
}
public static String undecorateDuplicitOptionName(String name) {
return removeSuffix(name, DUPLICIT_OPTION_SUFFIX);
}
}

View File

@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
@ -42,7 +43,7 @@ import org.keycloak.quarkus.runtime.Messages;
import org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand;
import org.keycloak.quarkus.runtime.cli.command.AbstractCommand;
import org.keycloak.quarkus.runtime.cli.command.AbstractNonServerCommand;
import org.keycloak.quarkus.runtime.cli.command.HelpAllMixin;
import org.keycloak.quarkus.runtime.cli.command.Build;
import org.keycloak.quarkus.runtime.cli.command.Main;
import org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource;
import org.keycloak.quarkus.runtime.configuration.Configuration;
@ -76,9 +77,6 @@ import picocli.CommandLine.ParseResult;
import static java.lang.String.format;
import static org.keycloak.quarkus.runtime.Environment.getProviderFiles;
import static org.keycloak.quarkus.runtime.Environment.isRebuildCheck;
import static org.keycloak.quarkus.runtime.cli.OptionRenderer.decorateDuplicitOptionName;
import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.OPTIMIZED_BUILD_OPTION_LONG;
import static org.keycloak.quarkus.runtime.configuration.Configuration.isUserModifiable;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
@ -93,9 +91,7 @@ public class Picocli {
public static final String ARG_SHORT_PREFIX = "-";
public static final String NO_PARAM_LABEL = "none";
private static class IncludeOptions {
boolean includeRuntime;
boolean includeBuildTime;
private record IncludeOptions(boolean includeRuntime, boolean includeBuildTime) {
}
private final ExecutionExceptionHandler errorHandler = new ExecutionExceptionHandler();
@ -133,15 +129,15 @@ public class Picocli {
CommandLine cl = commandLineList.get(commandLineList.size() - 1);
AbstractCommand currentCommand = null;
AbstractCommand currentCommand;
if (cl.getCommand() instanceof AbstractCommand ac) {
currentCommand = ac;
} else {
currentCommand = null;
}
initConfig(cliArgs, currentCommand);
initConfig(currentCommand);
if (!unrecognizedArgs.isEmpty()) {
IncludeOptions options = Optional.ofNullable(currentCommand).map(c -> getIncludeOptions(cliArgs, c, c.getName())).orElse(new IncludeOptions());
Set<OptionCategory> allowedCategories = Set.copyOf(Optional.ofNullable(currentCommand).map(AbstractCommand::getOptionCategories).orElse(List.of()));
// TODO: further refactor this as these args should be the source for ConfigArgsConfigSource
unrecognizedArgs.removeIf(arg -> {
boolean hasArg = false;
@ -151,11 +147,8 @@ public class Picocli {
}
PropertyMapper<?> mapper = PropertyMappers.getMapperByCliKey(arg);
if (mapper != null) {
if (!allowedCategories.contains(mapper.getCategory()) || (mapper.isBuildTime() && !options.includeBuildTime) || (mapper.isRunTime() && !options.includeRuntime)) {
return false;
}
if (!hasArg) {
addCommandOptions(cliArgs, cl);
addCommandOptions(cl, currentCommand);
throw new MissingParameterException(cl, cl.getCommandSpec().optionsMap().get(arg), null);
}
return true;
@ -163,13 +156,13 @@ public class Picocli {
return false;
});
if (!unrecognizedArgs.isEmpty()) {
addCommandOptions(cliArgs, cl);
addCommandOptions(cl, currentCommand);
throw new KcUnmatchedArgumentException(cl, unrecognizedArgs);
}
}
if (isHelpRequested(result)) {
addCommandOptions(cliArgs, cl);
addCommandOptions(cl, currentCommand);
}
// ParseResult retain memory. Clear it, so it's not on the stack while the command runs
@ -219,17 +212,15 @@ public class Picocli {
/**
* Additional validation and handling of deprecated options
*
* @param cliArgs
* @param abstractCommand
*/
public void validateConfig(List<String> cliArgs, AbstractCommand abstractCommand) {
if (cliArgs.contains(OPTIMIZED_BUILD_OPTION_LONG) && !wasBuildEverRun()) {
public void validateConfig() {
AbstractCommand abstractCommand = this.getParsedCommand().orElseThrow();
if (abstractCommand.isOptimized() && !wasBuildEverRun()) {
throw new PropertyException(Messages.optimizedUsedForFirstStartup());
}
warnOnDuplicatedOptionsInCli();
IncludeOptions options = getIncludeOptions(cliArgs, abstractCommand, abstractCommand.getName());
IncludeOptions options = getIncludeOptions(abstractCommand);
if (!options.includeBuildTime && !options.includeRuntime) {
return;
@ -249,6 +240,7 @@ public class Picocli {
final Set<String> deprecatedInUse = new LinkedHashSet<>();
final Set<String> missingOption = new LinkedHashSet<>();
final Set<String> ambiguousSpi = new LinkedHashSet<>();
final Set<String> unnecessary = new LinkedHashSet<>();
final LinkedHashMap<String, String> secondClassOptions = new LinkedHashMap<>();
final Set<PropertyMapper<?>> disabledMappers = new HashSet<>();
@ -259,8 +251,6 @@ public class Picocli {
disabledMappers.addAll(PropertyMappers.getDisabledRuntimeMappers().values());
}
var categories = new HashSet<>(abstractCommand.getOptionCategories());
// first validate the advertised property names
// - this allows for efficient resolution of wildcard values and checking spi options
Configuration.getPropertyNames().forEach(name -> {
@ -277,37 +267,26 @@ public class Picocli {
if (mapper == null) {
return; // TODO: need to look for disabled Wildcard mappers
}
String from = mapper.forKey(name).getFrom();
if (!name.equals(from)) {
var forKey = mapper.forKey(name);
if (!name.equals(forKey.getFrom())) {
ConfigValue value = getUnmappedValue(name);
if (value.getValue() != null && isUserModifiable(value)) {
secondClassOptions.put(name, from);
secondClassOptions.put(name, forKey.getFrom());
}
}
if (!mapper.hasWildcard()) {
return; // non-wildcard options will be validated in the next pass
}
if (!categories.contains(mapper.getCategory())) {
return; // not of interest to this command
// TODO: due to picking values up from the env and auto-builds, this probably isn't correct
// - the same issue exists with the second pass
}
validateProperty(abstractCommand, options, ignoredRunTime, disabledBuildTime, disabledRunTime,
deprecatedInUse, missingOption, disabledMappers, mapper, from);
deprecatedInUse, missingOption, disabledMappers.contains(mapper), forKey, unnecessary);
});
// second pass validate any property mapper not seen in the first pass
// - this will catch required values, anything missing from the property names
List<PropertyMapper<?>> mappers = new ArrayList<>();
for (OptionCategory category : categories) {
Optional.ofNullable(PropertyMappers.getRuntimeMappers().get(category)).ifPresent(mappers::addAll);
Optional.ofNullable(PropertyMappers.getBuildTimeMappers().get(category)).ifPresent(mappers::addAll);
}
for (PropertyMapper<?> mapper : mappers) {
// - this will catch required values, anything missing from the property names, or disabled
for (PropertyMapper<?> mapper : PropertyMappers.getMappers()) {
if (!mapper.hasWildcard()) {
validateProperty(abstractCommand, options, ignoredRunTime, disabledBuildTime, disabledRunTime,
deprecatedInUse, missingOption, disabledMappers, mapper, mapper.getFrom());
deprecatedInUse, missingOption, disabledMappers.contains(mapper), mapper, unnecessary);
}
}
@ -317,7 +296,7 @@ public class Picocli {
for (PropertyMapper<?> mapper : disabledMappers) {
if (!mapper.hasWildcard()) {
validateProperty(abstractCommand, options, ignoredRunTime, disabledBuildTime, disabledRunTime,
deprecatedInUse, missingOption, disabledMappers, mapper, mapper.getFrom());
deprecatedInUse, missingOption, disabledMappers.contains(mapper), mapper, unnecessary);
}
}
@ -344,6 +323,9 @@ public class Picocli {
secondClassOptions.forEach((key, firstClass) -> {
warn("Please use the first-class option `%s` instead of `%s`".formatted(firstClass, key));
});
if (!unnecessary.isEmpty()) {
info("The following options were specified, but are typically not relevant for this command: " + String.join("\n", unnecessary));
}
} finally {
DisabledMappersInterceptor.enable(disabledMappersInterceptorEnabled);
}
@ -402,38 +384,14 @@ public class Picocli {
private void validateProperty(AbstractCommand abstractCommand, IncludeOptions options,
final List<String> ignoredRunTime, final Set<String> disabledBuildTime, final Set<String> disabledRunTime,
final Set<String> deprecatedInUse, final Set<String> missingOption,
final Set<PropertyMapper<?>> disabledMappers, PropertyMapper<?> mapper, String from) {
boolean disabled, PropertyMapper<?> mapper, final Set<String> unnecessary) {
if (mapper.isBuildTime() && !options.includeBuildTime) {
return; // no need to validate as we've already checked for changes in the build time state
}
ConfigValue configValue = getUnmappedValue(from);
ConfigValue configValue = getUnmappedValue(mapper.getFrom());
String configValueStr = configValue.getValue();
// don't consider missing or anything below standard env properties
if (configValueStr != null && !isUserModifiable(configValue)) {
return;
}
if (disabledMappers.contains(mapper)) {
// add an error message if there's a value, no enabled propertymapper, and it's not a cli value
// as some cli options may be directly on the command and not
// backed by a property mapper - if they are disabled that should have already been handled as
// an unrecognized arg
if (configValueStr != null && PropertyMappers.getMapper(from) == null
&& !PropertyMapper.isCliOption(configValue)) {
handleDisabled(mapper.isRunTime() ? disabledRunTime : disabledBuildTime, mapper);
}
return;
}
if (mapper.isRunTime() && !options.includeRuntime) {
if (configValueStr != null) {
ignoredRunTime.add(mapper.getFrom());
}
return;
}
if (configValueStr == null) {
if (mapper.isRequired()) {
handleRequired(missingOption, mapper);
@ -441,9 +399,33 @@ public class Picocli {
return;
}
if (!isUserModifiable(configValue)) {
return;
}
if (disabled) {
// add an error message if no enabled propertymapper, and it's not a cli value
// as some cli options may be directly on the command and not backed by a property mapper
// - if they are disabled that should have already been handled as an unrecognized arg
if (PropertyMappers.getMapper(mapper.getFrom()) == null
&& !PropertyMapper.isCliOption(configValue)) {
handleDisabled(mapper.isRunTime() ? disabledRunTime : disabledBuildTime, mapper);
}
return;
}
if (mapper.isRunTime() && !options.includeRuntime) {
ignoredRunTime.add(mapper.getFrom());
return;
}
mapper.validate(configValue);
mapper.getDeprecatedMetadata().ifPresent(metadata -> handleDeprecated(deprecatedInUse, mapper, configValueStr, metadata));
if (mapper.isRunTime() && PropertyMapper.isCliOption(configValue) && abstractCommand.isHiddenCategory(mapper.getCategory())) {
unnecessary.add(mapper.getCliFormat());
}
}
private static void checkRuntimeSpiOptions(String key, final List<String> ignoredRunTime) {
@ -656,96 +638,63 @@ public class Picocli {
return new PrintWriter(System.out, true);
}
private IncludeOptions getIncludeOptions(List<String> cliArgs, AbstractCommand abstractCommand, String commandName) {
IncludeOptions result = new IncludeOptions();
private IncludeOptions getIncludeOptions(AbstractCommand abstractCommand) {
if (abstractCommand == null) {
return result;
return new IncludeOptions(false, false);
}
result.includeRuntime = abstractCommand.includeRuntime();
result.includeBuildTime = abstractCommand.includeBuildTime();
if (!result.includeBuildTime && !result.includeRuntime) {
return result;
} else if (result.includeRuntime && !result.includeBuildTime) {
result.includeBuildTime = !cliArgs.contains(OPTIMIZED_BUILD_OPTION_LONG);
} else if (result.includeBuildTime && !result.includeRuntime) {
result.includeRuntime = isRebuildCheck();
}
return result;
boolean autoBuild = abstractCommand instanceof AbstractAutoBuildCommand;
boolean includeBuildTime = abstractCommand instanceof Build || (autoBuild && !abstractCommand.isOptimized());
return new IncludeOptions(autoBuild, includeBuildTime);
}
private void addCommandOptions(List<String> cliArgs, CommandLine command) {
if (command != null && command.getCommand() instanceof AbstractCommand) {
IncludeOptions options = getIncludeOptions(cliArgs, command.getCommand(), command.getCommandName());
private void addCommandOptions(CommandLine command, AbstractCommand ac) {
IncludeOptions options = getIncludeOptions(ac);
if (!options.includeBuildTime && !options.includeRuntime) {
return;
}
addOptionsToCli(command, options);
if (!options.includeBuildTime && !options.includeRuntime) {
return;
}
}
private void addOptionsToCli(CommandLine commandLine, IncludeOptions includeOptions) {
final Map<OptionCategory, List<PropertyMapper<?>>> mappers = new EnumMap<>(OptionCategory.class);
// Since we can't run sanitizeDisabledMappers sooner, PropertyMappers.getRuntime|BuildTimeMappers() at this point
// contain both enabled and disabled mappers. Actual filtering is done later (help command, validations etc.).
if (includeOptions.includeRuntime) {
mappers.putAll(PropertyMappers.getRuntimeMappers());
}
PropertyMappers.getRuntimeMappers().entrySet().forEach(e -> mappers.put(e.getKey(), new ArrayList<>(e.getValue())));
PropertyMappers.getBuildTimeMappers().entrySet().forEach(e -> mappers.computeIfAbsent(e.getKey(), category -> new ArrayList<>()).addAll(e.getValue()));
if (includeOptions.includeBuildTime) {
combinePropertyMappers(mappers, PropertyMappers.getBuildTimeMappers());
}
addMappedOptionsToArgGroups(commandLine, mappers);
addMappedOptionsToArgGroups(command, mappers, ac, options);
}
private static <T extends Map<OptionCategory, List<PropertyMapper<?>>>> void combinePropertyMappers(T origMappers, T additionalMappers) {
for (var entry : additionalMappers.entrySet()) {
final List<PropertyMapper<?>> result = origMappers.getOrDefault(entry.getKey(), new ArrayList<>());
result.addAll(entry.getValue());
origMappers.put(entry.getKey(), result);
}
}
private static void addMappedOptionsToArgGroups(CommandLine commandLine, Map<OptionCategory, List<PropertyMapper<?>>> propertyMappers) {
private static void addMappedOptionsToArgGroups(CommandLine commandLine, Map<OptionCategory, List<PropertyMapper<?>>> propertyMappers, AbstractCommand ac, IncludeOptions options) {
CommandSpec cSpec = commandLine.getCommandSpec();
for (OptionCategory category : ((AbstractCommand) commandLine.getCommand()).getOptionCategories()) {
List<PropertyMapper<?>> mappersInCategory = propertyMappers.get(category);
if (mappersInCategory == null) {
//picocli raises an exception when an ArgGroup is empty, so ignore it when no mappings found for a category.
continue;
}
for (Entry<OptionCategory, List<PropertyMapper<?>>> entry : propertyMappers.entrySet()) {
Set<String> names = new HashSet<String>();
OptionCategory category = entry.getKey();
ArgGroupSpec.Builder argGroupBuilder = ArgGroupSpec.builder()
.heading(category.getHeading() + ":")
.order(category.getOrder())
.validate(false);
final Set<String> alreadyPresentArgs = new HashSet<>();
for (PropertyMapper<?> mapper : mappersInCategory) {
for (PropertyMapper<?> mapper : entry.getValue()) {
String name = mapper.getCliFormat();
// Picocli doesn't allow to have multiple options with the same name. We need this in help-all which also prints
// currently disabled options which might have a duplicate among enabled options. This is to register the disabled
// options with a unique name in Picocli. To keep it simple, it adds just a suffix to the options, i.e. there cannot
// be more that 1 disabled option with a unique name.
if (cSpec.optionsMap().containsKey(name)) {
name = decorateDuplicitOptionName(name);
boolean hidden = mapper.isHidden() || ac.isHiddenCategory(mapper.getCategory())
|| (!options.includeBuildTime && mapper.isBuildTime())
|| (!options.includeRuntime && mapper.isRunTime());
if (hidden && ac.isHelpAll()) {
continue; // doesn't need defined
}
if (cSpec.optionsMap().containsKey(name) || alreadyPresentArgs.contains(name)) {
//when key is already added, don't add.
continue;
if (cSpec.optionsMap().containsKey(name)) {
continue; // command is dominant
}
if (ac.isHelpAll() && !names.add(name)) {
continue; // we sometimes duplicate mappers within the same command
}
OptionSpec.Builder optBuilder = OptionSpec.builder(name)
.description(getDecoratedOptionDescription(mapper))
.completionCandidates(() -> mapper.getExpectedValues().iterator())
.hidden(mapper.isHidden());
.hidden(hidden);
if (mapper.getParamLabel() != null) {
optBuilder.paramLabel(mapper.getParamLabel());
@ -770,8 +719,6 @@ public class Picocli {
optBuilder.type(String.class);
}
alreadyPresentArgs.add(name);
argGroupBuilder.addArg(optBuilder.build());
}
@ -938,14 +885,14 @@ public class Picocli {
QuarkusEntryPoint.main();
}
public void initConfig(List<String> cliArgs, AbstractCommand command) {
public void initConfig(AbstractCommand command) {
if (Configuration.isInitialized()) {
throw new IllegalStateException("Config should not be initialized until profile is determined");
}
this.parsedCommand = Optional.ofNullable(command);
if (!Environment.isRebuilt() && command instanceof AbstractAutoBuildCommand
&& !cliArgs.contains(OPTIMIZED_BUILD_OPTION_LONG)) {
&& !command.isOptimized()) {
Environment.setRebuildCheck(true);
}
@ -953,7 +900,7 @@ public class Picocli {
.or(() -> parsedCommand.map(AbstractCommand::getInitProfile)).orElse(Environment.PROD_PROFILE_VALUE);
Environment.setProfile(profile);
if (!cliArgs.contains(HelpAllMixin.HELP_ALL_OPTION)) {
if (parsedCommand.filter(AbstractCommand::isHelpAll).isEmpty()) {
parsedCommand.ifPresent(PropertyMappers::sanitizeDisabledMappers);
}
}

View File

@ -3,10 +3,8 @@ package org.keycloak.quarkus.runtime.cli;
import java.io.PrintWriter;
import java.util.Optional;
import java.util.function.BooleanSupplier;
import java.util.stream.Stream;
import org.keycloak.quarkus.runtime.cli.command.AbstractCommand;
import org.keycloak.quarkus.runtime.cli.command.Start;
import org.keycloak.quarkus.runtime.configuration.KcUnmatchedArgumentException;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
@ -22,8 +20,6 @@ import picocli.CommandLine.UnmatchedArgumentException;
import static java.lang.String.format;
import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.OPTIMIZED_BUILD_OPTION_LONG;
public class ShortErrorMessageHandler implements IParameterExceptionHandler {
@Override
@ -59,17 +55,8 @@ public class ShortErrorMessageHandler implements IParameterExceptionHandler {
errorMessage = "Unknown option: '" + cliKey + "'";
}
} else {
AbstractCommand command = cmd.getCommand();
if (!command.getOptionCategories().contains(mapper.getCategory())) {
errorMessage = format("Option: '%s' not valid for command %s", cliKey, cmd.getCommandName());
} else {
if (Stream.of(args).anyMatch(OPTIMIZED_BUILD_OPTION_LONG::equals) && mapper.isBuildTime() && Start.NAME.equals(cmd.getCommandName())) {
errorMessage = format("Build time option: '%s' not usable with pre-built image and --optimized", cliKey);
} else {
final var optionType = mapper.isRunTime() ? "Run time" : "Build time";
errorMessage = format("%s option: '%s' not usable with %s", optionType, cliKey, cmd.getCommandName());
}
}
final var optionType = mapper.isRunTime() ? "Run time" : "Build time";
errorMessage = format("%s option: '%s' not usable with %s", optionType, cliKey, cmd.getCommandName());
}
} else if (ex instanceof MissingParameterException mpe) {
if (mpe.getMissing().size() == 1) {

View File

@ -18,14 +18,11 @@
package org.keycloak.quarkus.runtime.cli.command;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.keycloak.config.OptionCategory;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.cli.Picocli;
import org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource;
@ -101,7 +98,7 @@ public abstract class AbstractAutoBuildCommand extends AbstractCommand {
}
}
public void directBuild() {
void directBuild() {
Build build = new Build();
build.dryRunMixin = this.dryRunMixin;
build.setPicocli(picocli);
@ -148,13 +145,15 @@ public abstract class AbstractAutoBuildCommand extends AbstractCommand {
}
@Override
public List<OptionCategory> getOptionCategories() {
EnumSet<OptionCategory> excludedCategories = excludedCategories();
return super.getOptionCategories().stream().filter(optionCategory -> !excludedCategories.contains(optionCategory)).collect(Collectors.toList());
public boolean isHelpAll() {
return helpAllMixin != null ? helpAllMixin.allOptions : false;
}
protected EnumSet<OptionCategory> excludedCategories() {
return EnumSet.of(OptionCategory.IMPORT, OptionCategory.EXPORT);
abstract protected OptimizedMixin getOptimizedMixin();
@Override
public boolean isOptimized() {
return Optional.ofNullable(getOptimizedMixin()).map(o -> o.optimized).orElse(false);
}
@Override

View File

@ -17,15 +17,12 @@
package org.keycloak.quarkus.runtime.cli.command;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import org.keycloak.config.OptionCategory;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.cli.Picocli;
import org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource;
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
import picocli.CommandLine;
@ -91,28 +88,15 @@ public abstract class AbstractCommand implements Callable<Integer> {
}
/**
* Returns true if this command should include runtime options for the CLI.
* @param category
* @return true if runtime options for the given category should be hidden from the cli
*/
public boolean includeRuntime() {
return false;
}
/**
* Returns true if this command should include build time options for the CLI.
*/
public boolean includeBuildTime() {
return false;
}
/**
* Returns a list of all option categories which are available for this command.
*/
public List<OptionCategory> getOptionCategories() {
return Arrays.asList(OptionCategory.values());
public boolean isHiddenCategory(OptionCategory category) {
return category == OptionCategory.IMPORT || category == OptionCategory.EXPORT;
}
protected void validateConfig() {
picocli.validateConfig(ConfigArgsConfigSource.getAllCliArgs(), this);
picocli.validateConfig();
}
public abstract String getName();
@ -140,6 +124,18 @@ public abstract class AbstractCommand implements Callable<Integer> {
return false;
}
/**
* @return true if a form of help all was used. Only valid if this is the parsed command.
*/
public abstract boolean isHelpAll();
/**
* @return true if --optimized was used. Only valid if this is the parsed command.
*/
public boolean isOptimized() {
return false;
}
/**
* Controls whether the command actually starts the server
*/

View File

@ -17,8 +17,7 @@
package org.keycloak.quarkus.runtime.cli.command;
import java.util.List;
import java.util.stream.Collectors;
import java.util.EnumSet;
import org.keycloak.config.OptionCategory;
import org.keycloak.quarkus.runtime.Environment;
@ -31,30 +30,26 @@ public abstract class AbstractNonServerCommand extends AbstractAutoBuildCommand
@CommandLine.Mixin
OptimizedMixin optimizedMixin = new OptimizedMixin();
private static EnumSet<OptionCategory> hidden = EnumSet.of(OptionCategory.HTTP, OptionCategory.HTTP_ACCESS_LOG,
OptionCategory.PROXY, OptionCategory.HOSTNAME_V1, OptionCategory.HOSTNAME_V2, OptionCategory.METRICS,
OptionCategory.SECURITY, OptionCategory.CACHE, OptionCategory.HEALTH, OptionCategory.MANAGEMENT);
@Override
public String getDefaultProfile() {
return Environment.NON_SERVER_MODE;
}
@Override
public List<OptionCategory> getOptionCategories() {
return super.getOptionCategories().stream().filter(optionCategory ->
optionCategory != OptionCategory.HTTP &&
optionCategory != OptionCategory.PROXY &&
optionCategory != OptionCategory.HOSTNAME_V1 &&
optionCategory != OptionCategory.HOSTNAME_V2 &&
optionCategory != OptionCategory.METRICS &&
optionCategory != OptionCategory.SECURITY &&
optionCategory != OptionCategory.CACHE &&
optionCategory != OptionCategory.HEALTH).collect(Collectors.toList());
}
@Override
public boolean includeRuntime() {
return true;
public boolean isHiddenCategory(OptionCategory category) {
return super.isHiddenCategory(category) || hidden.contains(category);
}
public void onStart(QuarkusKeycloakApplication application) {
}
@Override
protected OptimizedMixin getOptimizedMixin() {
return optimizedMixin;
}
}

View File

@ -101,4 +101,9 @@ public abstract class AbstractUpdatesCommand extends AbstractAutoBuildCommand {
Config.init(configProvider);
}
@Override
protected OptimizedMixin getOptimizedMixin() {
return optimizedMixin;
}
}

View File

@ -17,8 +17,6 @@
package org.keycloak.quarkus.runtime.cli.command;
import java.util.EnumSet;
import org.keycloak.common.util.IoUtils;
import org.keycloak.config.BootstrapAdminOptions;
import org.keycloak.config.OptionCategory;
@ -109,8 +107,8 @@ public class BootstrapAdminService extends AbstractNonServerCommand {
}
@Override
protected EnumSet<OptionCategory> excludedCategories() {
return EnumSet.of(OptionCategory.IMPORT, OptionCategory.EXPORT, OptionCategory.BOOTSTRAP_ADMIN);
public boolean isHiddenCategory(OptionCategory category) {
return category == OptionCategory.BOOTSTRAP_ADMIN || super.isHiddenCategory(category);
}
}

View File

@ -17,8 +17,6 @@
package org.keycloak.quarkus.runtime.cli.command;
import java.util.EnumSet;
import org.keycloak.common.util.IoUtils;
import org.keycloak.config.BootstrapAdminOptions;
import org.keycloak.config.OptionCategory;
@ -109,8 +107,8 @@ public class BootstrapAdminUser extends AbstractNonServerCommand {
}
@Override
protected EnumSet<OptionCategory> excludedCategories() {
return EnumSet.of(OptionCategory.IMPORT, OptionCategory.EXPORT, OptionCategory.BOOTSTRAP_ADMIN);
public boolean isHiddenCategory(OptionCategory category) {
return category == OptionCategory.BOOTSTRAP_ADMIN || super.isHiddenCategory(category);
}
}

View File

@ -106,11 +106,6 @@ public final class Build extends AbstractCommand {
.ifPresent(s -> System.setProperty(QUARKUS_REMOVED_ARTIFACTS_PROPERTY, s));
}
@Override
public boolean includeBuildTime() {
return true;
}
private void checkProfileAndDb() {
if (Environment.isDevProfile()) {
String cmd = picocli.getParsedCommand().map(AbstractCommand::getName).orElse(getName());
@ -149,4 +144,10 @@ public final class Build extends AbstractCommand {
public String getName() {
return NAME;
}
@Override
public boolean isHelpAll() {
return helpAllMixin != null ? helpAllMixin.allOptions : false;
}
}

View File

@ -17,8 +17,6 @@
package org.keycloak.quarkus.runtime.cli.command;
import java.util.EnumSet;
import org.keycloak.config.OptionCategory;
import org.keycloak.exportimport.ExportImportConfig;
@ -44,8 +42,11 @@ public final class Export extends AbstractNonServerCommand {
}
@Override
protected EnumSet<OptionCategory> excludedCategories() {
return EnumSet.of(OptionCategory.IMPORT);
public boolean isHiddenCategory(OptionCategory category) {
if (category == OptionCategory.EXPORT) {
return false;
}
return super.isHiddenCategory(category);
}
}

View File

@ -17,8 +17,6 @@
package org.keycloak.quarkus.runtime.cli.command;
import org.keycloak.quarkus.runtime.cli.Help;
import picocli.CommandLine;
public final class HelpAllMixin {
@ -26,7 +24,6 @@ public final class HelpAllMixin {
public static final String HELP_ALL_OPTION = "--help-all";
@CommandLine.Option(names = {HELP_ALL_OPTION}, usageHelp = true, description = "This same help message but with additional options.")
public void setHelpAll(boolean allOptions) {
Help.setAllOptions(true);
}
boolean allOptions;
}

View File

@ -17,8 +17,6 @@
package org.keycloak.quarkus.runtime.cli.command;
import java.util.EnumSet;
import org.keycloak.config.OptionCategory;
import org.keycloak.exportimport.ExportImportConfig;
@ -47,8 +45,11 @@ public final class Import extends AbstractNonServerCommand {
}
@Override
protected EnumSet<OptionCategory> excludedCategories() {
return EnumSet.of(OptionCategory.EXPORT);
public boolean isHiddenCategory(OptionCategory category) {
if (category == OptionCategory.IMPORT) {
return false;
}
return super.isHiddenCategory(category);
}
}

View File

@ -28,6 +28,6 @@ public final class OptimizedMixin {
description = "Use this option to achieve an optimal startup time if you have previously built a server image using the 'build' command.",
paramLabel = NO_PARAM_LABEL,
order = 1)
Boolean optimized;
boolean optimized;
}

View File

@ -136,4 +136,10 @@ public final class ShowConfig extends AbstractCommand {
public String getName() {
return NAME;
}
@Override
public boolean isHelpAll() {
return false;
}
}

View File

@ -51,11 +51,6 @@ public final class Start extends AbstractAutoBuildCommand {
}
}
@Override
public boolean includeRuntime() {
return true;
}
@Override
public String getName() {
return NAME;
@ -65,4 +60,10 @@ public final class Start extends AbstractAutoBuildCommand {
public boolean isServing() {
return true;
}
@Override
protected OptimizedMixin getOptimizedMixin() {
return optimizedMixin;
}
}

View File

@ -46,11 +46,6 @@ public final class StartDev extends AbstractAutoBuildCommand {
return Environment.DEV_PROFILE_VALUE;
}
@Override
public boolean includeRuntime() {
return true;
}
@Override
public String getName() {
return NAME;
@ -60,4 +55,9 @@ public final class StartDev extends AbstractAutoBuildCommand {
public boolean isServing() {
return true;
}
@Override
protected OptimizedMixin getOptimizedMixin() {
return null;
}
}

View File

@ -79,11 +79,6 @@ public class UpdateCompatibilityCheck extends AbstractUpdatesCommand {
return NAME;
}
@Override
public boolean includeRuntime() {
return true;
}
@Override
protected void validateConfig() {
super.validateConfig();

View File

@ -60,11 +60,6 @@ public class UpdateCompatibilityMetadata extends AbstractUpdatesCommand {
return NAME;
}
@Override
public boolean includeRuntime() {
return true;
}
@Override
protected void validateConfig() {
super.validateConfig();

View File

@ -23,8 +23,6 @@ import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
import picocli.CommandLine;
import static org.keycloak.quarkus.runtime.cli.OptionRenderer.DUPLICIT_OPTION_SUFFIX;
/**
* Custom CommandLine.UnmatchedArgumentException with amended suggestions
*/
@ -42,8 +40,7 @@ public class KcUnmatchedArgumentException extends CommandLine.UnmatchedArgumentE
public List<String> getSuggestions() {
// filter out disabled mappers
return super.getSuggestions().stream()
.filter(f -> PropertyMappers.getKcKeyFromCliKey(f).filter(PropertyMappers::isDisabledMapper).isEmpty()
&& !f.endsWith(DUPLICIT_OPTION_SUFFIX))
.filter(f -> PropertyMappers.getKcKeyFromCliKey(f).filter(PropertyMappers::isDisabledMapper).isEmpty())
.toList();
}
}

View File

@ -542,15 +542,14 @@ public class PropertyMapper<T> {
* <p>
* f.e. check whether existing feature is referenced
* <pre>
* kc.feature-enabled-<feature>:v1
* kc.feature-<feature>:v1
* (key, value) -> is key a feature? if not, fail
*
* @param validator validator with parameters (wildcardKey, value)
*/
public Builder<T> wildcardKeysValidator(BiConsumer<String, String> validator) {
addValidator((mapper, configValue) -> {
var wildcardMapper = (WildcardPropertyMapper<?>) mapper;
var key = wildcardMapper.extractWildcardValue(configValue.getName()).orElseThrow(() -> new PropertyException("Cannot determine wildcard key."));
var key = mapper.getNamedProperty().orElseThrow(() -> new PropertyException("Cannot determine wildcard key."));
validator.accept(key, configValue.getValue());
});
return this;

View File

@ -23,7 +23,6 @@ import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.function.Consumer;
@ -105,10 +104,10 @@ public class PicocliTest extends AbstractConfigurationTest {
}
@Override
public void initConfig(List<String> cliArgs, AbstractCommand command) {
public void initConfig(AbstractCommand command) {
KeycloakConfigSourceProvider.reload();
boolean checkBuild = Environment.isRebuildCheck();
super.initConfig(cliArgs, command);
super.initConfig(command);
if (!checkBuild && PersistedConfigSource.getInstance().getConfigValueProperties().isEmpty()) {
System.getProperties().remove(Environment.KC_CONFIG_REBUILD_CHECK);
}
@ -373,6 +372,13 @@ public class PicocliTest extends AbstractConfigurationTest {
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
}
@Test
public void unnecessaryExportOption() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("export", "--dir=data", "--http-enabled=true");
assertThat(nonRunningPicocli.getOutString(), containsString("The following options were specified, but are typically not relevant for this command: --http-enabled"));
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
}
@Test
public void testReaugFromProdToDev() {
build("build", "--db=dev-file");
@ -621,9 +627,9 @@ public class PicocliTest extends AbstractConfigurationTest {
public void buildOptionChangedWithOptimized() {
build("build", "--db=dev-file");
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start", "--optimized", "--db=dev-mem");
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start", "--optimized", "--db=dev-mem", "--http-enabled=true", "--hostname-strict=false");
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertTrue(nonRunningPicocli.getErrString().contains("Build time option: '--db' not usable with pre-built image and --optimized"));
assertTrue(nonRunningPicocli.getErrString(), nonRunningPicocli.getErrString().contains("The following build time options have values that differ from what is persisted - the new values will NOT be used until another build is run: kc.db"));
}
@Test
@ -828,7 +834,6 @@ public class PicocliTest extends AbstractConfigurationTest {
nonRunningPicocli = pseudoLaunch("start-dev", "--log=%s".formatted(logHandlerName), "--log-%s-async-queue-length=768".formatted(logHandlerOptionsName));
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Disabled option: '--log-%s-async-queue-length'. Available only when %s is activated and asynchronous logging is enabled".formatted(logHandlerOptionsName, logHandlerFullName)));
}
@Test

View File

@ -65,8 +65,9 @@ class BuildCommandDistTest {
@Test
@Launch({ "build", "--db=postgres", "--db-username=myuser", "--db-password=mypassword", "--http-enabled=true" })
void testFailRuntimeOptions(CLIResult cliResult) {
cliResult.assertError("Run time option: '--db-username' not usable with build");
void testIgnoreRuntimeOptions(CLIResult cliResult) {
cliResult.assertMessage("The following run time options were found, but will be ignored during build time: kc.db-username, kc.http-enabled, kc.db-password");
cliResult.assertBuild();
}
@Test

View File

@ -147,69 +147,6 @@ Feature:
--features-disabled <feature>
Disables a set of one or more features. Possible values are: <...>.
HTTP Access log:
--http-access-log-enabled <true|false>
If HTTP access logging is enabled. By default this will log records in
console. Default: false.
Management:
--http-management-port <port>
Port of the management interface. Relevant only when something is exposed on
the management interface - see the guide for details. Default: 9000.
--http-management-relative-path <path>
Set the path relative to '/' for serving resources from management interface.
The path must start with a '/'. If not given, the value is inherited from
HTTP options. Relevant only when something is exposed on the management
interface - see the guide for details. Default: /.
--http-management-scheme <scheme>
Configures the management interface scheme. If 'inherited', the management
interface will inherit the HTTPS settings of the main interface. If 'http',
the management interface will be accessible via HTTP - it will not inherit
HTTPS settings and cannot be configured for HTTPS. Possible values are:
http, inherited. Default: inherited.
--https-management-certificate-file <file>
The file path to a server certificate or certificate chain in PEM format for
the management server. If not given, the value is inherited from HTTP
options. Relevant only when something is exposed on the management interface
- see the guide for details. Available only when http-management-scheme is
inherited.
--https-management-certificate-key-file <file>
The file path to a private key in PEM format for the management server. If not
given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Available only when http-management-scheme is inherited.
--https-management-certificates-reload-period <reload period>
Interval on which to reload key store, trust store, and certificate files
referenced by https-management-* options for the management server. May be
an ISO 8601 duration value, an integer number of seconds, or an integer
followed by one of [ms, h, m, s, d]. Must be greater than 30 seconds. Use -1
to disable. If not given, the value is inherited from HTTP options. Relevant
only when something is exposed on the management interface - see the guide
for details. Default: 1h. Available only when http-management-scheme is
inherited.
--https-management-client-auth <auth>
Configures the management interface to require/request client authentication.
If not given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Possible values are: none, request, required. Default: none.
--https-management-key-store-file <file>
The key store which holds the certificate information instead of specifying
separate files for the management server. If not given, the value is
inherited from HTTP options. Relevant only when something is exposed on the
management interface - see the guide for details. Available only when
http-management-scheme is inherited.
--https-management-key-store-password <password>
The password of the key store file for the management server. If not given,
the value is inherited from HTTP options. Relevant only when something is
exposed on the management interface - see the guide for details. Default:
password. Available only when http-management-scheme is inherited.
--legacy-observability-interface <true|false>
DEPRECATED. If metrics/health endpoints should be exposed on the main HTTP
server (not recommended). If set to true, the management interface is
disabled. Default: false.
Vault:
--vault <provider> Enables a vault provider. Possible values are: file, keystore.

View File

@ -149,69 +149,6 @@ Feature:
--features-disabled <feature>
Disables a set of one or more features. Possible values are: <...>.
HTTP Access log:
--http-access-log-enabled <true|false>
If HTTP access logging is enabled. By default this will log records in
console. Default: false.
Management:
--http-management-port <port>
Port of the management interface. Relevant only when something is exposed on
the management interface - see the guide for details. Default: 9000.
--http-management-relative-path <path>
Set the path relative to '/' for serving resources from management interface.
The path must start with a '/'. If not given, the value is inherited from
HTTP options. Relevant only when something is exposed on the management
interface - see the guide for details. Default: /.
--http-management-scheme <scheme>
Configures the management interface scheme. If 'inherited', the management
interface will inherit the HTTPS settings of the main interface. If 'http',
the management interface will be accessible via HTTP - it will not inherit
HTTPS settings and cannot be configured for HTTPS. Possible values are:
http, inherited. Default: inherited.
--https-management-certificate-file <file>
The file path to a server certificate or certificate chain in PEM format for
the management server. If not given, the value is inherited from HTTP
options. Relevant only when something is exposed on the management interface
- see the guide for details. Available only when http-management-scheme is
inherited.
--https-management-certificate-key-file <file>
The file path to a private key in PEM format for the management server. If not
given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Available only when http-management-scheme is inherited.
--https-management-certificates-reload-period <reload period>
Interval on which to reload key store, trust store, and certificate files
referenced by https-management-* options for the management server. May be
an ISO 8601 duration value, an integer number of seconds, or an integer
followed by one of [ms, h, m, s, d]. Must be greater than 30 seconds. Use -1
to disable. If not given, the value is inherited from HTTP options. Relevant
only when something is exposed on the management interface - see the guide
for details. Default: 1h. Available only when http-management-scheme is
inherited.
--https-management-client-auth <auth>
Configures the management interface to require/request client authentication.
If not given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Possible values are: none, request, required. Default: none.
--https-management-key-store-file <file>
The key store which holds the certificate information instead of specifying
separate files for the management server. If not given, the value is
inherited from HTTP options. Relevant only when something is exposed on the
management interface - see the guide for details. Available only when
http-management-scheme is inherited.
--https-management-key-store-password <password>
The password of the key store file for the management server. If not given,
the value is inherited from HTTP options. Relevant only when something is
exposed on the management interface - see the guide for details. Default:
password. Available only when http-management-scheme is inherited.
--legacy-observability-interface <true|false>
DEPRECATED. If metrics/health endpoints should be exposed on the main HTTP
server (not recommended). If set to true, the management interface is
disabled. Default: false.
Vault:
--vault <provider> Enables a vault provider. Possible values are: file, keystore.

View File

@ -142,69 +142,6 @@ Feature:
--features-disabled <feature>
Disables a set of one or more features. Possible values are: <...>.
HTTP Access log:
--http-access-log-enabled <true|false>
If HTTP access logging is enabled. By default this will log records in
console. Default: false.
Management:
--http-management-port <port>
Port of the management interface. Relevant only when something is exposed on
the management interface - see the guide for details. Default: 9000.
--http-management-relative-path <path>
Set the path relative to '/' for serving resources from management interface.
The path must start with a '/'. If not given, the value is inherited from
HTTP options. Relevant only when something is exposed on the management
interface - see the guide for details. Default: /.
--http-management-scheme <scheme>
Configures the management interface scheme. If 'inherited', the management
interface will inherit the HTTPS settings of the main interface. If 'http',
the management interface will be accessible via HTTP - it will not inherit
HTTPS settings and cannot be configured for HTTPS. Possible values are:
http, inherited. Default: inherited.
--https-management-certificate-file <file>
The file path to a server certificate or certificate chain in PEM format for
the management server. If not given, the value is inherited from HTTP
options. Relevant only when something is exposed on the management interface
- see the guide for details. Available only when http-management-scheme is
inherited.
--https-management-certificate-key-file <file>
The file path to a private key in PEM format for the management server. If not
given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Available only when http-management-scheme is inherited.
--https-management-certificates-reload-period <reload period>
Interval on which to reload key store, trust store, and certificate files
referenced by https-management-* options for the management server. May be
an ISO 8601 duration value, an integer number of seconds, or an integer
followed by one of [ms, h, m, s, d]. Must be greater than 30 seconds. Use -1
to disable. If not given, the value is inherited from HTTP options. Relevant
only when something is exposed on the management interface - see the guide
for details. Default: 1h. Available only when http-management-scheme is
inherited.
--https-management-client-auth <auth>
Configures the management interface to require/request client authentication.
If not given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Possible values are: none, request, required. Default: none.
--https-management-key-store-file <file>
The key store which holds the certificate information instead of specifying
separate files for the management server. If not given, the value is
inherited from HTTP options. Relevant only when something is exposed on the
management interface - see the guide for details. Available only when
http-management-scheme is inherited.
--https-management-key-store-password <password>
The password of the key store file for the management server. If not given,
the value is inherited from HTTP options. Relevant only when something is
exposed on the management interface - see the guide for details. Default:
password. Available only when http-management-scheme is inherited.
--legacy-observability-interface <true|false>
DEPRECATED. If metrics/health endpoints should be exposed on the main HTTP
server (not recommended). If set to true, the management interface is
disabled. Default: false.
Vault:
--vault <provider> Enables a vault provider. Possible values are: file, keystore.

View File

@ -142,83 +142,6 @@ Feature:
--features-disabled <feature>
Disables a set of one or more features. Possible values are: <...>.
HTTP Access log:
--http-access-log-enabled <true|false>
If HTTP access logging is enabled. By default this will log records in
console. Default: false.
--http-access-log-exclude <PARAM>
A regular expression that can be used to exclude some paths from logging. For
instance, '/realms/my-realm/.*' will exclude all subsequent endpoints for
realm 'my-realm' from the log. Available only when HTTP Access log is
enabled.
--http-access-log-pattern <PARAM>
The HTTP access log pattern. You can use the available named formats, or use
custom format described in Quarkus documentation. Possible values are:
common, combined, long, or a custom one. Default: common. Available only
when HTTP Access log is enabled.
Management:
--http-management-health-enabled <true|false>
If health endpoints should be exposed on the management interface. If false,
health endpoints will be exposed on the main interface. Default: true.
Available only when health is enabled.
--http-management-port <port>
Port of the management interface. Relevant only when something is exposed on
the management interface - see the guide for details. Default: 9000.
--http-management-relative-path <path>
Set the path relative to '/' for serving resources from management interface.
The path must start with a '/'. If not given, the value is inherited from
HTTP options. Relevant only when something is exposed on the management
interface - see the guide for details. Default: /.
--http-management-scheme <scheme>
Configures the management interface scheme. If 'inherited', the management
interface will inherit the HTTPS settings of the main interface. If 'http',
the management interface will be accessible via HTTP - it will not inherit
HTTPS settings and cannot be configured for HTTPS. Possible values are:
http, inherited. Default: inherited.
--https-management-certificate-file <file>
The file path to a server certificate or certificate chain in PEM format for
the management server. If not given, the value is inherited from HTTP
options. Relevant only when something is exposed on the management interface
- see the guide for details. Available only when http-management-scheme is
inherited.
--https-management-certificate-key-file <file>
The file path to a private key in PEM format for the management server. If not
given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Available only when http-management-scheme is inherited.
--https-management-certificates-reload-period <reload period>
Interval on which to reload key store, trust store, and certificate files
referenced by https-management-* options for the management server. May be
an ISO 8601 duration value, an integer number of seconds, or an integer
followed by one of [ms, h, m, s, d]. Must be greater than 30 seconds. Use -1
to disable. If not given, the value is inherited from HTTP options. Relevant
only when something is exposed on the management interface - see the guide
for details. Default: 1h. Available only when http-management-scheme is
inherited.
--https-management-client-auth <auth>
Configures the management interface to require/request client authentication.
If not given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Possible values are: none, request, required. Default: none.
--https-management-key-store-file <file>
The key store which holds the certificate information instead of specifying
separate files for the management server. If not given, the value is
inherited from HTTP options. Relevant only when something is exposed on the
management interface - see the guide for details. Available only when
http-management-scheme is inherited.
--https-management-key-store-password <password>
The password of the key store file for the management server. If not given,
the value is inherited from HTTP options. Relevant only when something is
exposed on the management interface - see the guide for details. Default:
password. Available only when http-management-scheme is inherited.
--legacy-observability-interface <true|false>
DEPRECATED. If metrics/health endpoints should be exposed on the main HTTP
server (not recommended). If set to true, the management interface is
disabled. Default: false.
Vault:
--vault <provider> Enables a vault provider. Possible values are: file, keystore.

View File

@ -142,69 +142,6 @@ Feature:
--features-disabled <feature>
Disables a set of one or more features. Possible values are: <...>.
HTTP Access log:
--http-access-log-enabled <true|false>
If HTTP access logging is enabled. By default this will log records in
console. Default: false.
Management:
--http-management-port <port>
Port of the management interface. Relevant only when something is exposed on
the management interface - see the guide for details. Default: 9000.
--http-management-relative-path <path>
Set the path relative to '/' for serving resources from management interface.
The path must start with a '/'. If not given, the value is inherited from
HTTP options. Relevant only when something is exposed on the management
interface - see the guide for details. Default: /.
--http-management-scheme <scheme>
Configures the management interface scheme. If 'inherited', the management
interface will inherit the HTTPS settings of the main interface. If 'http',
the management interface will be accessible via HTTP - it will not inherit
HTTPS settings and cannot be configured for HTTPS. Possible values are:
http, inherited. Default: inherited.
--https-management-certificate-file <file>
The file path to a server certificate or certificate chain in PEM format for
the management server. If not given, the value is inherited from HTTP
options. Relevant only when something is exposed on the management interface
- see the guide for details. Available only when http-management-scheme is
inherited.
--https-management-certificate-key-file <file>
The file path to a private key in PEM format for the management server. If not
given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Available only when http-management-scheme is inherited.
--https-management-certificates-reload-period <reload period>
Interval on which to reload key store, trust store, and certificate files
referenced by https-management-* options for the management server. May be
an ISO 8601 duration value, an integer number of seconds, or an integer
followed by one of [ms, h, m, s, d]. Must be greater than 30 seconds. Use -1
to disable. If not given, the value is inherited from HTTP options. Relevant
only when something is exposed on the management interface - see the guide
for details. Default: 1h. Available only when http-management-scheme is
inherited.
--https-management-client-auth <auth>
Configures the management interface to require/request client authentication.
If not given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Possible values are: none, request, required. Default: none.
--https-management-key-store-file <file>
The key store which holds the certificate information instead of specifying
separate files for the management server. If not given, the value is
inherited from HTTP options. Relevant only when something is exposed on the
management interface - see the guide for details. Available only when
http-management-scheme is inherited.
--https-management-key-store-password <password>
The password of the key store file for the management server. If not given,
the value is inherited from HTTP options. Relevant only when something is
exposed on the management interface - see the guide for details. Default:
password. Available only when http-management-scheme is inherited.
--legacy-observability-interface <true|false>
DEPRECATED. If metrics/health endpoints should be exposed on the main HTTP
server (not recommended). If set to true, the management interface is
disabled. Default: false.
Vault:
--vault <provider> Enables a vault provider. Possible values are: file, keystore.

View File

@ -142,83 +142,6 @@ Feature:
--features-disabled <feature>
Disables a set of one or more features. Possible values are: <...>.
HTTP Access log:
--http-access-log-enabled <true|false>
If HTTP access logging is enabled. By default this will log records in
console. Default: false.
--http-access-log-exclude <PARAM>
A regular expression that can be used to exclude some paths from logging. For
instance, '/realms/my-realm/.*' will exclude all subsequent endpoints for
realm 'my-realm' from the log. Available only when HTTP Access log is
enabled.
--http-access-log-pattern <PARAM>
The HTTP access log pattern. You can use the available named formats, or use
custom format described in Quarkus documentation. Possible values are:
common, combined, long, or a custom one. Default: common. Available only
when HTTP Access log is enabled.
Management:
--http-management-health-enabled <true|false>
If health endpoints should be exposed on the management interface. If false,
health endpoints will be exposed on the main interface. Default: true.
Available only when health is enabled.
--http-management-port <port>
Port of the management interface. Relevant only when something is exposed on
the management interface - see the guide for details. Default: 9000.
--http-management-relative-path <path>
Set the path relative to '/' for serving resources from management interface.
The path must start with a '/'. If not given, the value is inherited from
HTTP options. Relevant only when something is exposed on the management
interface - see the guide for details. Default: /.
--http-management-scheme <scheme>
Configures the management interface scheme. If 'inherited', the management
interface will inherit the HTTPS settings of the main interface. If 'http',
the management interface will be accessible via HTTP - it will not inherit
HTTPS settings and cannot be configured for HTTPS. Possible values are:
http, inherited. Default: inherited.
--https-management-certificate-file <file>
The file path to a server certificate or certificate chain in PEM format for
the management server. If not given, the value is inherited from HTTP
options. Relevant only when something is exposed on the management interface
- see the guide for details. Available only when http-management-scheme is
inherited.
--https-management-certificate-key-file <file>
The file path to a private key in PEM format for the management server. If not
given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Available only when http-management-scheme is inherited.
--https-management-certificates-reload-period <reload period>
Interval on which to reload key store, trust store, and certificate files
referenced by https-management-* options for the management server. May be
an ISO 8601 duration value, an integer number of seconds, or an integer
followed by one of [ms, h, m, s, d]. Must be greater than 30 seconds. Use -1
to disable. If not given, the value is inherited from HTTP options. Relevant
only when something is exposed on the management interface - see the guide
for details. Default: 1h. Available only when http-management-scheme is
inherited.
--https-management-client-auth <auth>
Configures the management interface to require/request client authentication.
If not given, the value is inherited from HTTP options. Relevant only when
something is exposed on the management interface - see the guide for
details. Possible values are: none, request, required. Default: none.
--https-management-key-store-file <file>
The key store which holds the certificate information instead of specifying
separate files for the management server. If not given, the value is
inherited from HTTP options. Relevant only when something is exposed on the
management interface - see the guide for details. Available only when
http-management-scheme is inherited.
--https-management-key-store-password <password>
The password of the key store file for the management server. If not given,
the value is inherited from HTTP options. Relevant only when something is
exposed on the management interface - see the guide for details. Default:
password. Available only when http-management-scheme is inherited.
--legacy-observability-interface <true|false>
DEPRECATED. If metrics/health endpoints should be exposed on the main HTTP
server (not recommended). If set to true, the management interface is
disabled. Default: false.
Vault:
--vault <provider> Enables a vault provider. Possible values are: file, keystore.