diff --git a/.github/workflows/operator-ci.yml b/.github/workflows/operator-ci.yml index e6dfc156b2b..ea1cdba4cc3 100644 --- a/.github/workflows/operator-ci.yml +++ b/.github/workflows/operator-ci.yml @@ -76,11 +76,11 @@ jobs: run: | eval $(minikube -p minikube docker-env) (cd quarkus/container && docker build --build-arg KEYCLOAK_DIST=$(ls keycloak-*.tar.gz) . -t keycloak:${{ steps.vars.outputs.version }}) - (cd operator && ./scripts/build-testing-docker-images.sh ${{ steps.vars.outputs.version }} keycloak custom-keycloak) + (cd operator/app && ./scripts/build-testing-docker-images.sh ${{ steps.vars.outputs.version }} keycloak custom-keycloak) - name: Test operator running locally run: | - mvn -Poperator -pl operator -am clean verify \ + mvn clean verify -Poperator -pl :keycloak-operator -am \ -Dquarkus.kubernetes.deployment-target=kubernetes \ -Doperator.keycloak.image=keycloak:${{ steps.vars.outputs.version }} \ -Dtest.operator.custom.image=custom-keycloak:${{ steps.vars.outputs.version }} \ @@ -121,12 +121,12 @@ jobs: run: | eval $(minikube -p minikube docker-env) (cd quarkus/container && docker build --build-arg KEYCLOAK_DIST=$(ls keycloak-*.tar.gz) . -t keycloak:${{ steps.vars.outputs.version }}) - (cd operator && ./scripts/build-testing-docker-images.sh ${{ steps.vars.outputs.version }} keycloak custom-keycloak) + (cd operator/app && ./scripts/build-testing-docker-images.sh ${{ steps.vars.outputs.version }} keycloak custom-keycloak) - name: Test operator running in cluster run: | eval $(minikube -p minikube docker-env) - mvn -Poperator -pl operator -am clean verify \ + mvn clean verify -Poperator -pl :keycloak-operator -am \ -Dquarkus.container-image.build=true \ -Dquarkus.kubernetes.deployment-target=kubernetes \ -Doperator.keycloak.image=keycloak:${{ steps.vars.outputs.version }} \ @@ -163,7 +163,7 @@ jobs: - name: Install Yq run: sudo snap install yq - name: Install OLM - working-directory: operator + working-directory: operator/app run: ./scripts/install-olm.sh - name: Download keycloak distribution id: download-keycloak-dist @@ -172,13 +172,13 @@ jobs: name: keycloak-distribution path: quarkus/container - name: Arrange OLM test installation - working-directory: operator + working-directory: operator/app run: | eval $(minikube -p minikube docker-env) ./scripts/olm-testing.sh ${GITHUB_SHA::6} - name: Deploy an example Keycloak and wait for it to be ready - working-directory: operator + working-directory: operator/app run: | kubectl apply -f src/main/resources/example-postgres.yaml ./scripts/check-crds-installed.sh diff --git a/config-api/pom.xml b/config-api/pom.xml new file mode 100755 index 00000000000..0608f0e2762 --- /dev/null +++ b/config-api/pom.xml @@ -0,0 +1,41 @@ + + + + + + keycloak-parent + org.keycloak + 999-SNAPSHOT + ../pom.xml + + 4.0.0 + + keycloak-config-api + Keycloak Configuration API + jar + + + + UTF-8 + 11 + 11 + 11 + + + diff --git a/config-api/src/main/java/org/keycloak/config/AllOptions.java b/config-api/src/main/java/org/keycloak/config/AllOptions.java new file mode 100644 index 00000000000..a33e0657d14 --- /dev/null +++ b/config-api/src/main/java/org/keycloak/config/AllOptions.java @@ -0,0 +1,13 @@ +package org.keycloak.config; + +import java.util.ArrayList; +import java.util.List; + +public class AllOptions { + + public final static List> ALL_OPTIONS = new ArrayList<>(); + + static { + ALL_OPTIONS.addAll(HttpOptions.ALL_OPTIONS); + } +} diff --git a/config-api/src/main/java/org/keycloak/config/HttpOptions.java b/config-api/src/main/java/org/keycloak/config/HttpOptions.java new file mode 100644 index 00000000000..7dd7b1a8c56 --- /dev/null +++ b/config-api/src/main/java/org/keycloak/config/HttpOptions.java @@ -0,0 +1,20 @@ +package org.keycloak.config; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class HttpOptions { + + public final static Option httpPort = new OptionBuilder("http-port", Integer.class) + .description("The used HTTP port.") + .category(OptionCategory.HTTP) + .defaultValue(8080) + .build(); + + public final static List> ALL_OPTIONS = new ArrayList<>(); + + static { + ALL_OPTIONS.add(httpPort); + } +} diff --git a/config-api/src/main/java/org/keycloak/config/Option.java b/config-api/src/main/java/org/keycloak/config/Option.java new file mode 100644 index 00000000000..2c67bf7a73a --- /dev/null +++ b/config-api/src/main/java/org/keycloak/config/Option.java @@ -0,0 +1,65 @@ +package org.keycloak.config; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public class Option { + + public enum Runtime { + QUARKUS, + DOCS, + OPERATOR; + } + + private final Class type; + private final String key; + private final OptionCategory category; + private final Set supportedRuntimes; + private final boolean buildTime; + private final String description; + private final Optional defaultValue; + private final List expectedValues; + + public Option(Class type, String key, OptionCategory category, Set supportedRuntimes, boolean buildTime, String description, Optional defaultValue, List expectedValues) { + this.type = type; + this.key = key; + this.category = category; + this.supportedRuntimes = supportedRuntimes; + this.buildTime = buildTime; + this.description = description; + this.defaultValue = defaultValue; + this.expectedValues = expectedValues; + } + + public Class getType() { + return type; + } + + public Set getSupportedRuntimes() { + return supportedRuntimes; + } + + public boolean isBuildTime() { + return buildTime; + } + + public String getKey() { + return key; + } + + public OptionCategory getCategory() { + return category; + } + + public String getDescription() { return description; } + + public Optional getDefaultValue() { + return defaultValue; + } + + public List getExpectedValues() { + return expectedValues; + } + +} diff --git a/config-api/src/main/java/org/keycloak/config/OptionBuilder.java b/config-api/src/main/java/org/keycloak/config/OptionBuilder.java new file mode 100644 index 00000000000..89f440c9adc --- /dev/null +++ b/config-api/src/main/java/org/keycloak/config/OptionBuilder.java @@ -0,0 +1,85 @@ +package org.keycloak.config; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +public class OptionBuilder { + private Class type; + private String key; + private OptionCategory category; + private Set supportedRuntimes; + private boolean build; + private String description; + private Optional defaultValue; + private List expectedValues; + + public OptionBuilder(String key, Class type) { + this.type = type; + this.key = key; + category = OptionCategory.GENERAL; + supportedRuntimes = Arrays.stream(Option.Runtime.values()).collect(Collectors.toSet()); + build = false; + description = ""; + defaultValue = Optional.empty(); + expectedValues = new ArrayList<>(); + } + + public OptionBuilder category(OptionCategory category) { + this.category = category; + return this; + } + + public OptionBuilder runtimes(Option.Runtime ... runtimes) { + this.supportedRuntimes.clear(); + this.supportedRuntimes.addAll(Arrays.asList(runtimes)); + return this; + } + + public OptionBuilder runtimes(Set runtimes) { + this.supportedRuntimes.clear(); + this.supportedRuntimes.addAll(runtimes); + return this; + } + + public OptionBuilder buildTime(boolean build) { + this.build = build; + return this; + } + + public OptionBuilder description(String description) { + this.description = description; + return this; + } + + public OptionBuilder defaultValue(Optional defaultV) { + this.defaultValue = defaultV; + return this; + } + + public OptionBuilder defaultValue(T defaultV) { + this.defaultValue = Optional.ofNullable(defaultV); + return this; + } + + public OptionBuilder expectedValues(List expected) { + this.expectedValues.clear(); + this.expectedValues.addAll(expected); + return this; + } + + public OptionBuilder expectedValues(T ... expected) { + this.expectedValues.clear(); + this.expectedValues.addAll(Arrays.asList(expected)); + return this; + } + + public Option build() { + return new Option(type, key, category, supportedRuntimes, build, description, defaultValue, expectedValues); + } + +} diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ConfigCategory.java b/config-api/src/main/java/org/keycloak/config/OptionCategory.java similarity index 83% rename from quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ConfigCategory.java rename to config-api/src/main/java/org/keycloak/config/OptionCategory.java index 30a9236898e..957d5dd0657 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/ConfigCategory.java +++ b/config-api/src/main/java/org/keycloak/config/OptionCategory.java @@ -1,6 +1,6 @@ -package org.keycloak.quarkus.runtime.configuration.mappers; +package org.keycloak.config; -public enum ConfigCategory { +public enum OptionCategory { // ordered by name asc CLUSTERING("Cluster", 10), DATABASE("Database", 20), @@ -20,7 +20,7 @@ public enum ConfigCategory { //Categories with a lower number are shown before groups with a higher number private final int order; - ConfigCategory(String heading, int order) { + OptionCategory(String heading, int order) { this.heading = heading; this.order = order; } diff --git a/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Options.java b/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Options.java index a915b3e624c..0f71b65d60f 100644 --- a/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Options.java +++ b/docs/maven-plugin/src/main/java/org/keycloak/guides/maven/Options.java @@ -5,25 +5,22 @@ import static org.keycloak.quarkus.runtime.configuration.Configuration.toDashCas import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX; import org.apache.commons.lang3.ArrayUtils; +import org.keycloak.config.OptionCategory; import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderFactory; import org.keycloak.provider.ProviderManager; import org.keycloak.provider.Spi; import org.keycloak.quarkus.runtime.Providers; import org.keycloak.quarkus.runtime.configuration.Configuration; -import org.keycloak.quarkus.runtime.configuration.mappers.ConfigCategory; -import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper; import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers; import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -36,7 +33,7 @@ public class Options { options = PropertyMappers.getMappers().stream() .filter(m -> !m.isHidden()) .filter(propertyMapper -> Objects.nonNull(propertyMapper.getDescription())) - .map(m -> new Option(m.getFrom(), m.getCategory(), m.isBuildTime(), m.getDescription(), m.getDefaultValue(), m.getExpectedValues())) + .map(m -> new Option(m.getFrom(), m.getCategory(), m.isBuildTime(), m.getDescription(), (String) m.getDefaultValue().map(d -> d.toString()).orElse(null), m.getExpectedValues())) .sorted(Comparator.comparing(Option::getKey)) .collect(Collectors.toMap(Option::getKey, o -> o, (o1, o2) -> o1, LinkedHashMap::new)); // Need to ignore duplicate keys?? ProviderManager providerManager = Providers.getProviderManager(Thread.currentThread().getContextClassLoader()); @@ -51,7 +48,7 @@ public class Options { String optionPrefix = NS_KEYCLOAK_PREFIX + String.join(OPTION_PART_SEPARATOR, ArrayUtils.insert(0, new String[] {loadSpi.getName(), providerFactory.getId()}, "spi")); List