From 9feca6566599e9eaad5602e25e62d48b8751bcbd Mon Sep 17 00:00:00 2001 From: AvivGuiser Date: Wed, 6 Aug 2025 10:09:42 +0300 Subject: [PATCH] feat(operator): add support for custom labels in ingress (#41627) Signed-off-by: AvivGuiser --- .../KeycloakIngressDependentResource.java | 1 + .../v2alpha1/deployment/spec/IngressSpec.java | 11 +++++++++ .../testsuite/unit/IngressLogicTest.java | 23 +++++++++++++++---- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/operator/src/main/java/org/keycloak/operator/controllers/KeycloakIngressDependentResource.java b/operator/src/main/java/org/keycloak/operator/controllers/KeycloakIngressDependentResource.java index d583796ace4..3ab8c944de7 100644 --- a/operator/src/main/java/org/keycloak/operator/controllers/KeycloakIngressDependentResource.java +++ b/operator/src/main/java/org/keycloak/operator/controllers/KeycloakIngressDependentResource.java @@ -115,6 +115,7 @@ public class KeycloakIngressDependentResource extends CRUDKubernetesDependentRes .withNewMetadata() .withName(getName(keycloak)) .withNamespace(keycloak.getMetadata().getNamespace()) + .addToLabels(optionalSpec.map(IngressSpec::getLabels).orElse(null)) .addToLabels(Utils.allInstanceLabels(keycloak)) .addToAnnotations(annotations) .endMetadata() diff --git a/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/IngressSpec.java b/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/IngressSpec.java index 0a98b3b9f54..ef0bff1bf4c 100644 --- a/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/IngressSpec.java +++ b/operator/src/main/java/org/keycloak/operator/crds/v2alpha1/deployment/spec/IngressSpec.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; import io.sundr.builder.annotations.Buildable; +import java.util.LinkedHashMap; import java.util.Map; @JsonInclude(JsonInclude.Include.NON_NULL) @@ -41,6 +42,10 @@ public class IngressSpec { @JsonPropertyDescription("A secret containing the TLS configuration for re-encrypt or TLS termination scenarios. Reference: https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets.") private String tlsSecret; + @JsonProperty("labels") + @JsonPropertyDescription("Additional labels to be appended to the Ingress object") + Map labels = new LinkedHashMap(); + public boolean isIngressEnabled() { return ingressEnabled; } @@ -72,4 +77,10 @@ public class IngressSpec { public void setTlsSecret(String tlsSecret) { this.tlsSecret = tlsSecret; } + public Map getLabels() { + return labels; + } + public void setLabels(Map labels) { + this.labels = labels; + } } diff --git a/operator/src/test/java/org/keycloak/operator/testsuite/unit/IngressLogicTest.java b/operator/src/test/java/org/keycloak/operator/testsuite/unit/IngressLogicTest.java index 3efa7ffb934..0c5bb637bc2 100644 --- a/operator/src/test/java/org/keycloak/operator/testsuite/unit/IngressLogicTest.java +++ b/operator/src/test/java/org/keycloak/operator/testsuite/unit/IngressLogicTest.java @@ -61,18 +61,22 @@ public class IngressLogicTest { } public static MockKeycloakIngress build(Boolean defaultIngressEnabled, boolean ingressExists, boolean ingressSpecDefined, boolean tlsConfigured) { - return build(defaultIngressEnabled, ingressExists, ingressSpecDefined, tlsConfigured, null, null); + return build(defaultIngressEnabled, ingressExists, ingressSpecDefined, tlsConfigured, null,null, null); } public static MockKeycloakIngress build(String hostname) { - return build(true, false, true, true, null, hostname); + return build(true, false, true, true, null,null, hostname); } public static MockKeycloakIngress build(Boolean defaultIngressEnabled, boolean ingressExists, boolean ingressSpecDefined, boolean tlsConfigured, Map annotations) { - return build(defaultIngressEnabled, ingressExists, ingressSpecDefined, tlsConfigured, annotations, null); + return build(defaultIngressEnabled, ingressExists, ingressSpecDefined, tlsConfigured, annotations,null, null); } - public static MockKeycloakIngress build(Boolean defaultIngressEnabled, boolean ingressExists, boolean ingressSpecDefined, boolean tlsConfigured, Map annotations, String hostname) { + public static MockKeycloakIngress build(Boolean defaultIngressEnabled, boolean ingressExists, boolean ingressSpecDefined,Map labels) { + return build(defaultIngressEnabled, ingressExists, ingressSpecDefined, true, null, labels, null); + } + + public static MockKeycloakIngress build(Boolean defaultIngressEnabled, boolean ingressExists, boolean ingressSpecDefined, boolean tlsConfigured, Map annotations, Map labels,String hostname) { IngressSpec ingressSpec = null; if (ingressSpecDefined) { ingressSpec = new IngressSpec(); @@ -82,6 +86,9 @@ public class IngressLogicTest { if (annotations != null) { ingressSpec.setAnnotations(annotations); } + if (labels != null) { + ingressSpec.setLabels(labels); + } } MockKeycloakIngress mock = new MockKeycloakIngress(tlsConfigured, ingressSpec, hostname); if (ingressExists) { @@ -183,6 +190,14 @@ public class IngressLogicTest { assertEquals("value", reconciled.get().getMetadata().getAnnotations().get("custom")); assertFalse(reconciled.get().getMetadata().getAnnotations().containsKey(EXISTING_ANNOTATION_KEY)); } + @Test + public void testCustomLabels() { + var kc = MockKeycloakIngress.build(null, false, true, Map.of("custom", "value")); + Optional reconciled = kc.getReconciledResource(); + assertTrue(reconciled.isPresent()); + assertFalse(kc.deleted()); + assertEquals("value", reconciled.get().getMetadata().getLabels().get("custom")); + } @Test public void testRemoveCustomAnnotation() {