Sorting the chapters of the HA guide

Closes #38721

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
Alexander Schwartz
2025-04-11 13:37:07 +02:00
committed by GitHub
parent 74188c33e4
commit 4e93379254
9 changed files with 61 additions and 30 deletions

View File

@@ -1,13 +1,16 @@
introduction
concepts-multi-site
bblocks-multi-site
concepts-database-connections
concepts-threads
concepts-memory-and-cpu-sizing
concepts-infinispan-cli-batch
deploy-aurora-multi-az
deploy-infinispan-kubernetes-crossdc
deploy-keycloak-kubernetes
deploy-aws-route53-loadbalancer
deploy-aws-route53-failover-lambda
health-checks-multi-site
operate-failover
operate-switch-over
operate-network-partition-recovery
operate-switch-back
deploy-aws-accelerator-loadbalancer
deploy-aws-accelerator-fencing-lambda
operate-site-offline
operate-site-online
operate-synchronize
health-checks-multi-site

View File

@@ -3,4 +3,12 @@ configuration-metrics
event-metrics
keycloak-service-level-indicators
metrics-for-troubleshooting
metrics-for-troubleshooting-keycloak
metrics-for-troubleshooting-jvm
metrics-for-troubleshooting-database
metrics-for-troubleshooting-http
metrics-for-troubleshooting-clustering-and-network
metrics-for-troubleshooting-embedded-caches
metrics-for-troubleshooting-embedded-caches-multi-site
metrics-for-troubleshooting-external-infinispan-multi-site
tracing

View File

@@ -6,7 +6,6 @@
<@tmpl.guide
title="Basic {project_name} deployment"
priority=20
summary="How to install {project_name} using the Operator">
== Performing a basic {project_name} deployment
@@ -100,9 +99,9 @@ When running on OpenShift, with ingress enabled, and with the spec.ingress.class
The operator will assign a default hostname to the stored version of the CR similar to what would be created by an OpenShift Route without an explicit host - that is ingress-namespace.appsDomain
If the appsDomain changes, or should you need a different hostname for any reason, then update the Keycloak CR.
NOTE: If you set the `hostname-admin`, or the deprecated `hostname-admin-url`, even if you enable ingress, no ingress will be created specifically for admin access.
Admin access via a separate hostname is generally expected to have access restrictions, which are not currently expressible via the Keycloak CR.
Also the default ingress does not prevent accessing admin endpoints, so you may not want to enable ingress handling via the Keycloak CR at all when you have a separate hostname for admin endpoints.
NOTE: If you set the `hostname-admin`, or the deprecated `hostname-admin-url`, even if you enable ingress, no ingress will be created specifically for admin access.
Admin access via a separate hostname is generally expected to have access restrictions, which are not currently expressible via the Keycloak CR.
Also the default ingress does not prevent accessing admin endpoints, so you may not want to enable ingress handling via the Keycloak CR at all when you have a separate hostname for admin endpoints.
==== TLS Certificate and key

View File

@@ -6,7 +6,6 @@
<@tmpl.guide
title="{project_name} Operator Installation"
priority=10
summary="How to install the {project_name} Operator on Kubernetes and OpenShift">
== Installing the {project_name} Operator
@@ -64,7 +63,7 @@ kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resourc
kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/{version}/kubernetes/kubernetes.yml
----
The Operator will watch the namespace where it is installed. You may optionally select a namespace with the `-n` option.
The Operator will watch the namespace where it is installed. You may optionally select a namespace with the `-n` option.
</@profile.ifCommunity>
=== Installing Multiple Operators
@@ -79,6 +78,6 @@ If you do this please be aware:
- older CRDs may not be forwards compatible with new fields used by newer operators. When using OLM it will check if your custom resources are compatible with the CRDs being installed, so the usage of new fields can prevent the simultaneous installation of older operator versions.
- fields introduced by newer CRDs will not be supported by older Operators. Older Operator will fail to handle CRs that use such new fields with an error deserializing an unrecognized field.
It is therefore recommended in a multiple Operator install scenario that you keep versions aligned as closely as possible to minimize the potential problems with different versions.
It is therefore recommended in a multiple Operator install scenario that you keep versions aligned as closely as possible to minimize the potential problems with different versions.
</@tmpl.guide>

View File

@@ -5,7 +5,6 @@
<@tmpl.guide
title="{project_name} Realm Import"
priority=30
summary="How to perform an automated {project_name} Realm Import using the operator">
== Importing a {project_name} Realm
@@ -85,10 +84,10 @@ When the import has successfully completed, the output will look like the follow
----
CONDITION: Done
STATUS: true
MESSAGE:
MESSAGE:
CONDITION: Started
STATUS: false
MESSAGE:
MESSAGE:
CONDITION: HasErrors
STATUS: false
MESSAGE:
@@ -96,7 +95,7 @@ CONDITION: HasErrors
=== Placeholders
Imports support placeholders referencing environment variables, see <@links.server id="importExport"/> for more.
Imports support placeholders referencing environment variables, see <@links.server id="importExport"/> for more.
The `KeycloakRealmImport` CR allows you to leverage this functionality via the `spec.placeholders` stanza, for example:
[source,yaml]
@@ -115,7 +114,7 @@ spec:
...
----
In the above example placeholder replacement will be enabled and an environment variable with key `ENV_KEY` will be created from the Secret `SECRET_NAME`'s value for key `SECRET_KEY`.
In the above example placeholder replacement will be enabled and an environment variable with key `ENV_KEY` will be created from the Secret `SECRET_NAME`'s value for key `SECRET_KEY`.
Currently only Secrets are supported and they must be in the same namespace as the Keycloak CR.
</@tmpl.guide>

View File

@@ -4,7 +4,6 @@
<@tmpl.guide
title="Using a vault"
summary="Learn how to use and configure a vault in {project_name}"
priority=30
includedOptions="vault vault-*">
{project_name} provides two out-of-the-box implementations of the Vault SPI: a plain-text file-based vault and Java KeyStore-based vault.

View File

@@ -31,16 +31,30 @@ public class Context {
for (File f : srcDir.listFiles((dir, f) -> f.endsWith(".adoc") && !f.equals("index.adoc"))) {
Guide guide = parser.parse(f);
if (guidePriorities != null && guide != null) {
Integer priority = guidePriorities.get(guide.getId());
guide.setPriority(priority != null ? priority : Integer.MAX_VALUE);
}
if (guide != null) {
if (guidePriorities != null) {
Integer priority = guidePriorities.get(guide.getId());
if (priority != null) {
if (guide.getPriority() != Integer.MAX_VALUE) {
throw new RuntimeException("Guide is pinned, but has a priority specified: " + f.getName());
}
guidePriorities.remove(guide.getId());
guide.setPriority(priority);
}
}
if (!guide.isTileVisible() && guide.getPriority() == Integer.MAX_VALUE) {
throw new RuntimeException("Invisible tiles should be pinned or have an explicit priority: " + f.getName());
}
guides.add(guide);
}
}
if (guidePriorities != null && !guidePriorities.isEmpty()) {
throw new RuntimeException("File 'pinned-guides' contains files that no longer exist or are misspelled: " + guidePriorities.keySet());
}
Collections.sort(guides, (o1, o2) -> {
if (o1.getPriority() == o2.getPriority()) {
return o1.getTitle().compareTo(o2.getTitle());

View File

@@ -6,7 +6,8 @@ public class Guide {
private String id;
private String title;
private String summary;
private int priority;
private int priority = Integer.MAX_VALUE;
private boolean tileVisible = true;
public String getTemplate() {
return template;
@@ -47,4 +48,12 @@ public class Guide {
public void setPriority(int priority) {
this.priority = priority;
}
public boolean isTileVisible() {
return tileVisible;
}
public void setTileVisible(boolean tileVisible) {
this.tileVisible = tileVisible;
}
}

View File

@@ -9,8 +9,8 @@ import java.util.regex.Pattern;
public class GuideParser {
private Pattern TEMPLATE_IMPORT_PATTERN = Pattern.compile("<#import \"/templates/guide.adoc\" as (?<importName>[^ ]*)>");
private Pattern GUIDE_ELEMENT_PATTERN = Pattern.compile("(?<key>priority|title|summary)=(\\\"(?<valueString>[^\\\"]*)\\\"|(?<valueInt>[\\d]*))");
private final Pattern TEMPLATE_IMPORT_PATTERN = Pattern.compile("<#import \"/templates/guide.adoc\" as (?<importName>[^ ]*)>");
private final Pattern GUIDE_ELEMENT_PATTERN = Pattern.compile("(?<key>priority|title|summary|tileVisible)=(\\\"(?<valueString>[^\\\"]*)\\\"|(?<valueInt>[\\d]*))");
/**
* Parses a FreeMarker template to retrieve Guide attributes
@@ -26,7 +26,6 @@ public class GuideParser {
if (importElement != null) {
Guide guide = new Guide();
guide.setTemplate(file.getName());
guide.setPriority(999);
guide.setId(file.getName().replaceAll(".adoc", ""));
@@ -79,6 +78,8 @@ public class GuideParser {
break;
case "priority":
guide.setPriority(Integer.parseInt(attributeMatcher.group("valueInt")));
case "tileVisible":
guide.setTileVisible(Boolean.parseBoolean(attributeMatcher.group("valueString")));
}
}
}