enhance: adding a start optimized flag (#25216)
closes: #25015 Update docs/guides/operator/customizing-keycloak.adoc Update docs/documentation/release_notes/topics/24_0_0.adoc Update operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/KeycloakSpec.java Signed-off-by: Václav Muzikář <vmuzikar@redhat.com> Co-authored-by: Václav Muzikář <vaclav@muzikari.cz>
This commit is contained in:
parent
0f5bbae75c
commit
4db4982e9d
7 changed files with 82 additions and 10 deletions
|
@ -23,3 +23,9 @@ The endpoint is currently checking availability of the embedded and external Inf
|
||||||
This endpoint is not available by default.
|
This endpoint is not available by default.
|
||||||
To enable it, run Keycloak with feature `multi-site`.
|
To enable it, run Keycloak with feature `multi-site`.
|
||||||
Proceed to https://www.keycloak.org/server/features[Enabling and disabling features] guide for more details.
|
Proceed to https://www.keycloak.org/server/features[Enabling and disabling features] guide for more details.
|
||||||
|
|
||||||
|
= Keycloak CR Optimized Field
|
||||||
|
|
||||||
|
The Keycloak CR now includes an `startOptimized` field, which may be used to override the default assumption about whether to use the `--optimized` flag for the start command.
|
||||||
|
As a result, you can use the CR to configure build time options also when a custom Keycloak image is used.
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,29 @@ spec:
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
With custom images, every build time option is passed either through a dedicated field or the `additionalOptions` is ignored.
|
With custom images, every build time option passed either through a dedicated field or the `additionalOptions` is ignored.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
=== Non-optimized custom image
|
||||||
|
|
||||||
|
While it is considered a best practice use a pre-augmented image, if you want to use a non-optimized custom image or build time properties with an augmented image that is still possible. You just need set the `startOptimzed` field to `false` as shown in this example:
|
||||||
|
|
||||||
|
[source,yaml]
|
||||||
|
----
|
||||||
|
apiVersion: k8s.keycloak.org/v2alpha1
|
||||||
|
kind: Keycloak
|
||||||
|
metadata:
|
||||||
|
name: example-kc
|
||||||
|
spec:
|
||||||
|
instances: 1
|
||||||
|
image: quay.io/my-company/my-keycloak:latest
|
||||||
|
startOptimized: false
|
||||||
|
http:
|
||||||
|
tlsSecret: example-tls-secret
|
||||||
|
hostname:
|
||||||
|
hostname: test.keycloak.org
|
||||||
|
----
|
||||||
|
|
||||||
|
Keep in mind this will incur the re-augmentation cost on every start.
|
||||||
|
|
||||||
</@tmpl.guide>
|
</@tmpl.guide>
|
||||||
|
|
|
@ -31,6 +31,7 @@ public interface Config {
|
||||||
interface Keycloak {
|
interface Keycloak {
|
||||||
String image();
|
String image();
|
||||||
String imagePullPolicy();
|
String imagePullPolicy();
|
||||||
|
boolean startOptimized();
|
||||||
|
|
||||||
Map<String, String> podLabels();
|
Map<String, String> podLabels();
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,9 @@ public class KeycloakDeploymentDependentResource extends CRUDKubernetesDependent
|
||||||
if (Optional.ofNullable(containerBuilder.getArgs()).orElse(List.of()).isEmpty()) {
|
if (Optional.ofNullable(containerBuilder.getArgs()).orElse(List.of()).isEmpty()) {
|
||||||
containerBuilder.withArgs("--verbose", "start");
|
containerBuilder.withArgs("--verbose", "start");
|
||||||
}
|
}
|
||||||
if (customImage.isPresent()) {
|
if (Boolean.TRUE.equals(keycloakCR.getSpec().getStartOptimized())
|
||||||
|
|| keycloakCR.getSpec().getStartOptimized() == null
|
||||||
|
&& (customImage.isPresent() || operatorConfig.keycloak().startOptimized())) {
|
||||||
containerBuilder.addToArgs(OPTIMIZED_ARG);
|
containerBuilder.addToArgs(OPTIMIZED_ARG);
|
||||||
}
|
}
|
||||||
containerBuilder.addToArgs(0, getJGroupsParameter(keycloakCR));
|
containerBuilder.addToArgs(0, getJGroupsParameter(keycloakCR));
|
||||||
|
|
|
@ -16,24 +16,24 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.operator.crds.v2alpha1.deployment;
|
package org.keycloak.operator.crds.v2alpha1.deployment;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
|
|
||||||
|
|
||||||
import io.fabric8.kubernetes.api.model.LocalObjectReference;
|
import io.fabric8.kubernetes.api.model.LocalObjectReference;
|
||||||
import io.fabric8.kubernetes.model.annotation.SpecReplicas;
|
import io.fabric8.kubernetes.model.annotation.SpecReplicas;
|
||||||
|
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.DatabaseSpec;
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.DatabaseSpec;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.FeatureSpec;
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.FeatureSpec;
|
||||||
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HostnameSpec;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec;
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.UnsupportedSpec;
|
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TransactionsSpec;
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TransactionsSpec;
|
||||||
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HostnameSpec;
|
import org.keycloak.operator.crds.v2alpha1.deployment.spec.UnsupportedSpec;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
|
||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public class KeycloakSpec {
|
public class KeycloakSpec {
|
||||||
|
|
||||||
|
@ -44,6 +44,9 @@ public class KeycloakSpec {
|
||||||
@JsonPropertyDescription("Custom Keycloak image to be used.")
|
@JsonPropertyDescription("Custom Keycloak image to be used.")
|
||||||
private String image;
|
private String image;
|
||||||
|
|
||||||
|
@JsonPropertyDescription("Set to force the behavior of the --optimized flag for the start command. If left unspecified the operator will assume custom images have already been augmented.")
|
||||||
|
private Boolean startOptimized;
|
||||||
|
|
||||||
@JsonPropertyDescription("Secret(s) that might be used when pulling an image from a private container image registry or repository.")
|
@JsonPropertyDescription("Secret(s) that might be used when pulling an image from a private container image registry or repository.")
|
||||||
private List<LocalObjectReference> imagePullSecrets;
|
private List<LocalObjectReference> imagePullSecrets;
|
||||||
|
|
||||||
|
@ -171,4 +174,12 @@ public class KeycloakSpec {
|
||||||
public void setAdditionalOptions(List<ValueOrSecret> additionalOptions) {
|
public void setAdditionalOptions(List<ValueOrSecret> additionalOptions) {
|
||||||
this.additionalOptions = additionalOptions;
|
this.additionalOptions = additionalOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getStartOptimized() {
|
||||||
|
return startOptimized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartOptimized(Boolean optimized) {
|
||||||
|
this.startOptimized = optimized;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ quarkus.banner.enabled=false
|
||||||
# Operator config
|
# Operator config
|
||||||
operator.keycloak.image=${RELATED_IMAGE_KEYCLOAK:quay.io/keycloak/keycloak:nightly}
|
operator.keycloak.image=${RELATED_IMAGE_KEYCLOAK:quay.io/keycloak/keycloak:nightly}
|
||||||
operator.keycloak.image-pull-policy=Always
|
operator.keycloak.image-pull-policy=Always
|
||||||
|
operator.keycloak.start-optimized=false
|
||||||
|
|
||||||
# https://quarkus.io/guides/deploying-to-kubernetes#environment-variables-from-keyvalue-pairs
|
# https://quarkus.io/guides/deploying-to-kubernetes#environment-variables-from-keyvalue-pairs
|
||||||
quarkus.kubernetes.env.vars.related-image-keycloak=${operator.keycloak.image}
|
quarkus.kubernetes.env.vars.related-image-keycloak=${operator.keycloak.image}
|
||||||
|
|
|
@ -371,6 +371,35 @@ public class PodTemplateTest {
|
||||||
var podTemplate = getDeployment(additionalPodTemplate).getSpec().getTemplate();
|
var podTemplate = getDeployment(additionalPodTemplate).getSpec().getTemplate();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertThat(podTemplate.getSpec().getContainers().get(0).getArgs()).doesNotContain("--optimized");
|
assertThat(podTemplate.getSpec().getContainers().get(0).getArgs()).doesNotContain(KeycloakDeploymentDependentResource.OPTIMIZED_ARG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImageNotOptimized() {
|
||||||
|
// Arrange
|
||||||
|
PodTemplateSpec additionalPodTemplate = null;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var podTemplate = getDeployment(additionalPodTemplate, null,
|
||||||
|
s -> s.withImage("some-image").withStartOptimized(false))
|
||||||
|
.getSpec().getTemplate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertThat(podTemplate.getSpec().getContainers().get(0).getArgs()).doesNotContain(KeycloakDeploymentDependentResource.OPTIMIZED_ARG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImageForceOptimized() {
|
||||||
|
// Arrange
|
||||||
|
PodTemplateSpec additionalPodTemplate = null;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var podTemplate = getDeployment(additionalPodTemplate, null,
|
||||||
|
s -> s.withStartOptimized(true))
|
||||||
|
.getSpec().getTemplate();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertThat(podTemplate.getSpec().getContainers().get(0).getCommand().contains(KeycloakDeploymentDependentResource.OPTIMIZED_ARG));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue