Improve enabling/disabling features in Quarkus distribution (#9801)
Closes #9706
This commit is contained in:
parent
2919342f3a
commit
7c162b42a6
13 changed files with 222 additions and 198 deletions
|
@ -4,7 +4,8 @@
|
|||
|
||||
<@tmpl.guide
|
||||
title="Enabling and disabling features"
|
||||
summary="Understand how to configure Keycloak to use optional features">
|
||||
summary="Understand how to configure Keycloak to use optional features"
|
||||
includedOptions="features features-*">
|
||||
|
||||
Keycloak has packed some functionality in features, some of them not enabled by default. These features include features that are in tech preview or deprecated features. In addition there are some features that are enabled by default, but can be disabled if you don't need them for your specific usage scenario.
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ import org.jboss.logging.Logger;
|
|||
import org.jboss.resteasy.plugins.server.servlet.ResteasyContextParameters;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.quarkus.runtime.QuarkusProfile;
|
||||
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.QuarkusPropertiesConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
|
||||
|
@ -244,7 +245,7 @@ class KeycloakProcessor {
|
|||
@Record(ExecutionTime.RUNTIME_INIT)
|
||||
@BuildStep
|
||||
KeycloakSessionFactoryPreInitBuildItem configureProviders(KeycloakRecorder recorder) {
|
||||
Profile.setInstance(recorder.createProfile());
|
||||
Profile.setInstance(new QuarkusProfile());
|
||||
Map<Spi, Map<Class<? extends Provider>, Map<String, Class<? extends ProviderFactory>>>> factories = new HashMap<>();
|
||||
Map<Class<? extends Provider>, String> defaultProviders = new HashMap<>();
|
||||
Map<String, ProviderFactory> preConfiguredProviders = new HashMap<>();
|
||||
|
|
|
@ -17,11 +17,8 @@
|
|||
|
||||
package org.keycloak.quarkus.runtime;
|
||||
|
||||
import static org.keycloak.quarkus.runtime.configuration.Configuration.getBuildTimeProperty;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
|
||||
import org.infinispan.configuration.parsing.ParserRegistry;
|
||||
|
@ -78,31 +75,10 @@ public class KeycloakRecorder {
|
|||
Map<Class<? extends Provider>, String> defaultProviders,
|
||||
Map<String, ProviderFactory> preConfiguredProviders,
|
||||
Boolean reaugmented) {
|
||||
Profile.setInstance(createProfile());
|
||||
Profile.setInstance(new QuarkusProfile());
|
||||
QuarkusKeycloakSessionFactory.setInstance(new QuarkusKeycloakSessionFactory(factories, defaultProviders, preConfiguredProviders, reaugmented));
|
||||
}
|
||||
|
||||
public static Profile createProfile() {
|
||||
return new Profile(new Profile.PropertyResolver() {
|
||||
@Override
|
||||
public String resolve(String feature) {
|
||||
if (feature.startsWith("keycloak.profile.feature")) {
|
||||
feature = feature.replaceFirst("keycloak\\.profile\\.feature.", "kc\\.features-");
|
||||
} else {
|
||||
feature = "kc.features";
|
||||
}
|
||||
|
||||
Optional<String> value = getBuildTimeProperty(feature);
|
||||
|
||||
if (value.isPresent()) {
|
||||
return value.get();
|
||||
}
|
||||
|
||||
return Configuration.getRawValue(feature);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public RuntimeValue<CacheManagerFactory> createCacheInitializer(String config, ShutdownContext shutdownContext) {
|
||||
try {
|
||||
ConfigurationBuilderHolder builder = new ParserRegistry().parse(config);
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.quarkus.runtime;
|
||||
|
||||
import static org.keycloak.quarkus.runtime.configuration.Configuration.getRawPersistedProperty;
|
||||
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.quarkus.runtime.configuration.Configuration;
|
||||
|
||||
public class QuarkusProfile extends Profile {
|
||||
|
||||
public QuarkusProfile() {
|
||||
super(new DefaultPropertyResolver());
|
||||
}
|
||||
|
||||
private static class DefaultPropertyResolver implements PropertyResolver {
|
||||
|
||||
@Override
|
||||
public String resolve(String key) {
|
||||
if (isFeaturePresent(key, getCurrentValue("kc.features"))) {
|
||||
if (isPreviewProfileKey(key)) {
|
||||
return Profile.Type.PREVIEW.name();
|
||||
}
|
||||
|
||||
return "enabled";
|
||||
}
|
||||
|
||||
if (isFeaturePresent(key, getCurrentValue("kc.features-disabled"))) {
|
||||
if (!isPreviewProfileKey(key)) {
|
||||
return "disabled";
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isFeaturePresent(String key, String features) {
|
||||
if (features == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String feature : features.split(",")) {
|
||||
if (isPreviewProfileKey(key)) {
|
||||
try {
|
||||
Profile.Type profileType = Profile.Type.valueOf(feature);
|
||||
|
||||
if (Profile.Type.PREVIEW.equals(profileType)) {
|
||||
return true;
|
||||
}
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (key.substring(key.lastIndexOf('.') + 1).toUpperCase().equals(feature)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isPreviewProfileKey(String key) {
|
||||
return key.equals("keycloak.profile");
|
||||
}
|
||||
|
||||
private String getCurrentValue(String name) {
|
||||
String enabledFeatures = getRawPersistedProperty(name).orElse(null);
|
||||
|
||||
if (enabledFeatures == null) {
|
||||
enabledFeatures = Configuration.getRawValue(name);
|
||||
}
|
||||
|
||||
if (enabledFeatures == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return enabledFeatures.toUpperCase().replace('-', '_');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,6 @@ 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.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -51,7 +50,6 @@ import org.keycloak.quarkus.runtime.cli.command.Build;
|
|||
import org.keycloak.quarkus.runtime.cli.command.Main;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Start;
|
||||
import org.keycloak.quarkus.runtime.cli.command.StartDev;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
|
||||
import org.keycloak.quarkus.runtime.configuration.mappers.ConfigCategory;
|
||||
|
@ -295,43 +293,11 @@ public final class Picocli {
|
|||
|
||||
if (includeBuildTime) {
|
||||
mappers.addAll(PropertyMappers.getBuildTimeMappers());
|
||||
addFeatureOptions(commandSpec);
|
||||
}
|
||||
|
||||
addMappedOptionsToArgGroups(commandSpec, mappers);
|
||||
}
|
||||
|
||||
private static void addFeatureOptions(CommandSpec commandSpec) {
|
||||
ArgGroupSpec.Builder featureGroupBuilder = ArgGroupSpec.builder()
|
||||
.heading(ConfigCategory.FEATURE.getHeading() + ":")
|
||||
.order(ConfigCategory.FEATURE.getOrder())
|
||||
.validate(false);
|
||||
|
||||
String previewName = Profile.Type.PREVIEW.name().toLowerCase();
|
||||
|
||||
featureGroupBuilder.addArg(OptionSpec.builder(new String[] {"-ft", "--features"})
|
||||
.description("Enables all tech preview features.")
|
||||
.paramLabel(previewName)
|
||||
.completionCandidates(Collections.singleton(previewName))
|
||||
.parameterConsumer(PropertyMapperParameterConsumer.INSTANCE)
|
||||
.type(String.class)
|
||||
.build());
|
||||
|
||||
List<String> expectedValues = asList("enabled", "disabled");
|
||||
|
||||
for (Profile.Feature feature : Profile.Feature.values()) {
|
||||
featureGroupBuilder.addArg(OptionSpec.builder("--features-" + feature.name().toLowerCase())
|
||||
.description("Enables the " + feature.name() + " feature.")
|
||||
.paramLabel(String.join("|", expectedValues))
|
||||
.type(String.class)
|
||||
.parameterConsumer(PropertyMapperParameterConsumer.INSTANCE)
|
||||
.completionCandidates(expectedValues)
|
||||
.build());
|
||||
}
|
||||
|
||||
commandSpec.addArgGroup(featureGroupBuilder.build());
|
||||
}
|
||||
|
||||
private static void addMappedOptionsToArgGroups(CommandSpec cSpec, List<PropertyMapper> propertyMappers) {
|
||||
for(ConfigCategory category : ConfigCategory.values()) {
|
||||
List<PropertyMapper> mappersInCategory = propertyMappers.stream()
|
||||
|
|
|
@ -19,8 +19,12 @@ package org.keycloak.quarkus.runtime.cli;
|
|||
|
||||
import static org.keycloak.quarkus.runtime.cli.Picocli.ARG_PREFIX;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.keycloak.utils.StringUtil;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Model.ArgSpec;
|
||||
|
@ -79,21 +83,23 @@ public final class PropertyMapperParameterConsumer implements CommandLine.IParam
|
|||
}
|
||||
|
||||
private boolean isExpectedValue(OptionSpec option, String value) {
|
||||
Iterator<String> expectedValues = option.completionCandidates().iterator();
|
||||
List<String> expectedValues = StreamSupport.stream(option.completionCandidates().spliterator(), false).collect(Collectors.toList());
|
||||
|
||||
if (!expectedValues.hasNext()) {
|
||||
if (expectedValues.isEmpty()) {
|
||||
// accept any
|
||||
return true;
|
||||
}
|
||||
|
||||
while (expectedValues.hasNext()) {
|
||||
String expectedValue = expectedValues.next();
|
||||
|
||||
if (expectedValue.equals(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtil.isBlank(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String v : value.split(",")) {
|
||||
if (!expectedValues.contains(v)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,10 +48,10 @@ import picocli.CommandLine.Mixin;
|
|||
footerHeading = "Examples:",
|
||||
footer = " Optimize the server based on a profile configuration:%n%n"
|
||||
+ " $ ${PARENT-COMMAND-FULL-NAME:-$PARENTCOMMAND} --profile=prod ${COMMAND-NAME} %n%n"
|
||||
+ " Change database settings:%n%n"
|
||||
+ " $ ${PARENT-COMMAND-FULL-NAME:-$PARENTCOMMAND} ${COMMAND-NAME} --db=postgres [--db-url][--db-username][--db-password]%n%n"
|
||||
+ " Change the database vendor:%n%n"
|
||||
+ " $ ${PARENT-COMMAND-FULL-NAME:-$PARENTCOMMAND} ${COMMAND-NAME} --db=postgres%n%n"
|
||||
+ " Enable a feature:%n%n"
|
||||
+ " $ ${PARENT-COMMAND-FULL-NAME:-$PARENTCOMMAND} ${COMMAND-NAME} --features-<feature_name>=[enabled|disabled]%n%n"
|
||||
+ " $ ${PARENT-COMMAND-FULL-NAME:-$PARENTCOMMAND} ${COMMAND-NAME} --features=<feature_name>%n%n"
|
||||
+ " Or alternatively, enable all tech preview features:%n%n"
|
||||
+ " $ ${PARENT-COMMAND-FULL-NAME:-$PARENTCOMMAND} ${COMMAND-NAME} --features=preview%n%n"
|
||||
+ " Enable metrics:%n%n"
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package org.keycloak.quarkus.runtime.configuration.mappers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.keycloak.common.Profile;
|
||||
|
||||
final class FeaturePropertyMappers {
|
||||
|
||||
private FeaturePropertyMappers() {
|
||||
}
|
||||
|
||||
public static PropertyMapper[] getMappers() {
|
||||
return new PropertyMapper[] {
|
||||
builder()
|
||||
.from("features")
|
||||
.description("Enables a set of one or more features.")
|
||||
.expectedValues(getFeatureValues())
|
||||
.paramLabel("feature")
|
||||
.build(),
|
||||
builder()
|
||||
.from("features-disabled")
|
||||
.expectedValues(getFeatureValues())
|
||||
.paramLabel("feature")
|
||||
.description("Disables a set of one or more features.")
|
||||
.build()
|
||||
};
|
||||
}
|
||||
|
||||
private static List<String> getFeatureValues() {
|
||||
List<String> features = new ArrayList<>();
|
||||
|
||||
for (Profile.Feature value : Profile.Feature.values()) {
|
||||
features.add(value.name().toLowerCase().replace('_', '-'));
|
||||
}
|
||||
|
||||
features.add(Profile.Type.PREVIEW.name().toLowerCase());
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
private static PropertyMapper.Builder builder() {
|
||||
return PropertyMapper.builder(ConfigCategory.FEATURE).isBuildTimeProperty(true);
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ public final class PropertyMappers {
|
|||
MAPPERS.addAll(MetricsPropertyMappers.getMetricsPropertyMappers());
|
||||
MAPPERS.addAll(ProxyPropertyMappers.getProxyPropertyMappers());
|
||||
MAPPERS.addAll(VaultPropertyMappers.getVaultPropertyMappers());
|
||||
MAPPERS.addAll(FeaturePropertyMappers.getMappers());
|
||||
}
|
||||
|
||||
public static ConfigValue getValue(ConfigSourceInterceptorContext context, String name) {
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* 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.cli.dist;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
|
||||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
|
||||
@DistributionTest
|
||||
class EnableFeatureDistTest {
|
||||
|
||||
@Test
|
||||
@Launch({ "build", "--features=preview" })
|
||||
void testEnablePreviewFeatures(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertMessage("Preview feature enabled: admin_fine_grained_authz");
|
||||
cliResult.assertMessage("Preview feature enabled: openshift_integration");
|
||||
cliResult.assertMessage("Preview feature enabled: scripts");
|
||||
cliResult.assertMessage("Preview feature enabled: token_exchange");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ "build", "--features-token_exchange=enabled" })
|
||||
void testEnableSinglefeature(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertMessage("Preview feature enabled: token_exchange");
|
||||
}
|
||||
}
|
|
@ -3,23 +3,71 @@ package org.keycloak.it.cli.dist;
|
|||
import io.quarkus.test.junit.main.Launch;
|
||||
import io.quarkus.test.junit.main.LaunchResult;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.keycloak.it.junit5.extension.CLIResult;
|
||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Build;
|
||||
import org.keycloak.quarkus.runtime.cli.command.Start;
|
||||
import org.keycloak.quarkus.runtime.cli.command.StartDev;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
@DistributionTest
|
||||
@RawDistOnly(reason = "Containers are immutable")
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class FeaturesDistTest {
|
||||
|
||||
@Test
|
||||
@Launch({ Build.NAME, "--features=preview", "--cache=local"})
|
||||
@Order(1)
|
||||
public void testEnableOnBuild(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertBuild();
|
||||
assertPreviewFeaturesEnabled(cliResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({ Start.NAME, "--http-enabled=true", "--hostname-strict=false"})
|
||||
@Order(2)
|
||||
public void testFeatureEnabledOnStart(LaunchResult result) {
|
||||
assertPreviewFeaturesEnabled((CLIResult) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({StartDev.NAME, "--features=preview"})
|
||||
public void testPreviewFeaturesGetEnabledWhenCliArgIsSet(LaunchResult result) {
|
||||
public void testEnablePreviewFeatures(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertStartedDevMode();
|
||||
assertPreviewFeaturesEnabled((CLIResult) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({StartDev.NAME, "--features=preview", "--features-disabled=token-exchange"})
|
||||
public void testEnablePrecedenceOverDisable(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertStartedDevMode();
|
||||
assertPreviewFeaturesEnabled((CLIResult) result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Launch({StartDev.NAME, "--features=token-exchange,admin-fine-grained-authz"})
|
||||
public void testEnableMultipleFeatures(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertStartedDevMode();
|
||||
assertThat(cliResult.getOutput(), CoreMatchers.allOf(
|
||||
containsString("Preview feature enabled: admin_fine_grained_authz"),
|
||||
containsString("Preview feature enabled: token_exchange")));
|
||||
assertFalse(cliResult.getOutput().contains("declarative-user-profile"));
|
||||
}
|
||||
|
||||
private void assertPreviewFeaturesEnabled(CLIResult result) {
|
||||
assertThat(result.getOutput(), CoreMatchers.allOf(
|
||||
containsString("Preview feature enabled: admin_fine_grained_authz"),
|
||||
containsString("Preview feature enabled: openshift_integration"),
|
||||
containsString("Preview feature enabled: scripts"),
|
||||
|
|
|
@ -41,44 +41,9 @@ Database:
|
|||
|
||||
Feature:
|
||||
|
||||
--features-account2 <enabled|disabled>
|
||||
Enables the ACCOUNT2 feature.
|
||||
--features-account_api <enabled|disabled>
|
||||
Enables the ACCOUNT_API feature.
|
||||
--features-admin2 <enabled|disabled>
|
||||
Enables the ADMIN2 feature.
|
||||
--features-admin_fine_grained_authz <enabled|disabled>
|
||||
Enables the ADMIN_FINE_GRAINED_AUTHZ feature.
|
||||
--features-authorization <enabled|disabled>
|
||||
Enables the AUTHORIZATION feature.
|
||||
--features-ciba <enabled|disabled>
|
||||
Enables the CIBA feature.
|
||||
--features-client_policies <enabled|disabled>
|
||||
Enables the CLIENT_POLICIES feature.
|
||||
--features-declarative_user_profile <enabled|disabled>
|
||||
Enables the DECLARATIVE_USER_PROFILE feature.
|
||||
--features-docker <enabled|disabled>
|
||||
Enables the DOCKER feature.
|
||||
--features-dynamic_scopes <enabled|disabled>
|
||||
Enables the DYNAMIC_SCOPES feature.
|
||||
--features-impersonation <enabled|disabled>
|
||||
Enables the IMPERSONATION feature.
|
||||
--features-map_storage <enabled|disabled>
|
||||
Enables the MAP_STORAGE feature.
|
||||
--features-openshift_integration <enabled|disabled>
|
||||
Enables the OPENSHIFT_INTEGRATION feature.
|
||||
--features-par <enabled|disabled>
|
||||
Enables the PAR feature.
|
||||
--features-scripts <enabled|disabled>
|
||||
Enables the SCRIPTS feature.
|
||||
--features-token_exchange <enabled|disabled>
|
||||
Enables the TOKEN_EXCHANGE feature.
|
||||
--features-upload_scripts <enabled|disabled>
|
||||
Enables the UPLOAD_SCRIPTS feature.
|
||||
--features-web_authn <enabled|disabled>
|
||||
Enables the WEB_AUTHN feature.
|
||||
-ft, --features <preview>
|
||||
Enables all tech preview features.
|
||||
--features <feature> Enables a set of one or more features.
|
||||
--features-disabled <feature>
|
||||
Disables a set of one or more features.
|
||||
|
||||
HTTP/TLS:
|
||||
|
||||
|
@ -102,13 +67,13 @@ Examples:
|
|||
|
||||
$ kc.sh --profile=prod build
|
||||
|
||||
Change database settings:
|
||||
Change the database vendor:
|
||||
|
||||
$ kc.sh build --db=postgres [--db-url][--db-username][--db-password]
|
||||
$ kc.sh build --db=postgres
|
||||
|
||||
Enable a feature:
|
||||
|
||||
$ kc.sh build --features-<feature_name>=[enabled|disabled]
|
||||
$ kc.sh build --features=<feature_name>
|
||||
|
||||
Or alternatively, enable all tech preview features:
|
||||
|
||||
|
|
|
@ -54,44 +54,9 @@ Database:
|
|||
|
||||
Feature:
|
||||
|
||||
--features-account2 <enabled|disabled>
|
||||
Enables the ACCOUNT2 feature.
|
||||
--features-account_api <enabled|disabled>
|
||||
Enables the ACCOUNT_API feature.
|
||||
--features-admin2 <enabled|disabled>
|
||||
Enables the ADMIN2 feature.
|
||||
--features-admin_fine_grained_authz <enabled|disabled>
|
||||
Enables the ADMIN_FINE_GRAINED_AUTHZ feature.
|
||||
--features-authorization <enabled|disabled>
|
||||
Enables the AUTHORIZATION feature.
|
||||
--features-ciba <enabled|disabled>
|
||||
Enables the CIBA feature.
|
||||
--features-client_policies <enabled|disabled>
|
||||
Enables the CLIENT_POLICIES feature.
|
||||
--features-declarative_user_profile <enabled|disabled>
|
||||
Enables the DECLARATIVE_USER_PROFILE feature.
|
||||
--features-docker <enabled|disabled>
|
||||
Enables the DOCKER feature.
|
||||
--features-dynamic_scopes <enabled|disabled>
|
||||
Enables the DYNAMIC_SCOPES feature.
|
||||
--features-impersonation <enabled|disabled>
|
||||
Enables the IMPERSONATION feature.
|
||||
--features-map_storage <enabled|disabled>
|
||||
Enables the MAP_STORAGE feature.
|
||||
--features-openshift_integration <enabled|disabled>
|
||||
Enables the OPENSHIFT_INTEGRATION feature.
|
||||
--features-par <enabled|disabled>
|
||||
Enables the PAR feature.
|
||||
--features-scripts <enabled|disabled>
|
||||
Enables the SCRIPTS feature.
|
||||
--features-token_exchange <enabled|disabled>
|
||||
Enables the TOKEN_EXCHANGE feature.
|
||||
--features-upload_scripts <enabled|disabled>
|
||||
Enables the UPLOAD_SCRIPTS feature.
|
||||
--features-web_authn <enabled|disabled>
|
||||
Enables the WEB_AUTHN feature.
|
||||
-ft, --features <preview>
|
||||
Enables all tech preview features.
|
||||
--features <feature> Enables a set of one or more features.
|
||||
--features-disabled <feature>
|
||||
Disables a set of one or more features.
|
||||
|
||||
Hostname:
|
||||
|
||||
|
|
Loading…
Reference in a new issue