From 0ecdebc000ca4450e45b08a8146b1eb28205942b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Barto=C5=A1?= Date: Fri, 16 Jun 2023 16:12:56 +0200 Subject: [PATCH] Incorrect Url on Keycloak Health - Liveness and Readiness, no Startup Probes Fixes #17388 --- .../controllers/KeycloakDeployment.java | 11 ++-- .../testsuite/unit/PodTemplateTest.java | 53 ++++++++++++++++--- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java b/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java index d527008ee0..f5b8985555 100644 --- a/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java +++ b/operator/src/main/java/org/keycloak/operator/controllers/KeycloakDeployment.java @@ -404,23 +404,26 @@ public class KeycloakDeployment extends OperatorManagedResource implements Statu // probes var tlsConfigured = isTlsConfigured(keycloakCR); - var userRelativePath = readConfigurationValue(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY); - var kcRelativePath = (userRelativePath == null) ? "" : userRelativePath; var protocol = !tlsConfigured ? "HTTP" : "HTTPS"; var kcPort = KeycloakService.getServicePort(keycloakCR); + // Relative path ends with '/' + var kcRelativePath = Optional.ofNullable(readConfigurationValue(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY)) + .map(path -> !path.endsWith("/") ? path + "/" : path) + .orElse("/"); + container.getReadinessProbe().setHttpGet( new HTTPGetActionBuilder() .withScheme(protocol) .withPort(new IntOrString(kcPort)) - .withPath(kcRelativePath + "/health/ready") + .withPath(kcRelativePath + "health/ready") .build() ); container.getLivenessProbe().setHttpGet( new HTTPGetActionBuilder() .withScheme(protocol) .withPort(new IntOrString(kcPort)) - .withPath(kcRelativePath + "/health/live") + .withPath(kcRelativePath + "health/live") .build() ); diff --git a/operator/src/test/java/org/keycloak/operator/testsuite/unit/PodTemplateTest.java b/operator/src/test/java/org/keycloak/operator/testsuite/unit/PodTemplateTest.java index 0df4642947..96b1935b46 100644 --- a/operator/src/test/java/org/keycloak/operator/testsuite/unit/PodTemplateTest.java +++ b/operator/src/test/java/org/keycloak/operator/testsuite/unit/PodTemplateTest.java @@ -17,6 +17,7 @@ package org.keycloak.operator.testsuite.unit; +import io.fabric8.kubernetes.api.model.Container; import io.fabric8.kubernetes.api.model.IntOrString; import io.fabric8.kubernetes.api.model.PodTemplateSpec; import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder; @@ -29,12 +30,15 @@ import org.keycloak.operator.Config; import org.keycloak.operator.controllers.KeycloakDeployment; import org.keycloak.operator.crds.v2alpha1.deployment.Keycloak; import org.keycloak.operator.crds.v2alpha1.deployment.KeycloakSpecBuilder; +import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret; import org.keycloak.operator.crds.v2alpha1.deployment.spec.HostnameSpecBuilder; import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpecBuilder; import org.keycloak.operator.crds.v2alpha1.deployment.spec.UnsupportedSpec; import java.util.Collections; import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -42,9 +46,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @QuarkusTest public class PodTemplateTest { - - private StatefulSet getDeployment(PodTemplateSpec podTemplate, StatefulSet existingDeployment) { - var config = new Config(){ + private StatefulSet getDeployment(PodTemplateSpec podTemplate, StatefulSet existingDeployment, Consumer additionalSpec) { + var config = new Config() { @Override public Keycloak keycloak() { return new Keycloak() { @@ -52,6 +55,7 @@ public class PodTemplateTest { public String image() { return "dummy-image"; } + @Override public String imagePullPolicy() { return "Never"; @@ -68,15 +72,25 @@ public class PodTemplateTest { var httpSpec = new HttpSpecBuilder().withTlsSecret("example-tls-secret").build(); var hostnameSpec = new HostnameSpecBuilder().withHostname("example.com").build(); - kc.setSpec(new KeycloakSpecBuilder().withUnsupported(new UnsupportedSpec(podTemplate)) + var keycloakSpecBuilder = new KeycloakSpecBuilder() + .withUnsupported(new UnsupportedSpec(podTemplate)) .withHttpSpec(httpSpec) - .withHostnameSpec(hostnameSpec) - .build()); + .withHostnameSpec(hostnameSpec); + + if (additionalSpec != null) { + additionalSpec.accept(keycloakSpecBuilder); + } + + kc.setSpec(keycloakSpecBuilder.build()); var deployment = new KeycloakDeployment(null, config, kc, existingDeployment, "dummy-admin"); return (StatefulSet) deployment.getReconciledResource().get(); } + private StatefulSet getDeployment(PodTemplateSpec podTemplate, StatefulSet existingDeployment) { + return getDeployment(podTemplate, existingDeployment, null); + } + private StatefulSet getDeployment(PodTemplateSpec podTemplate) { return getDeployment(podTemplate, new StatefulSet()); } @@ -281,4 +295,31 @@ public class PodTemplateTest { assertThat(podTemplate.getMetadata().getAnnotations()).containsEntry("one", "1"); assertThat(podTemplate.getMetadata().getAnnotations()).containsEntry("two", "2"); } + + @Test + public void testRelativePathHealthProbes() { + final Function setUpRelativePath = (path) -> getDeployment(null, new StatefulSet(), + spec -> spec.withAdditionalOptions(new ValueOrSecret("http-relative-path", path))) + .getSpec() + .getTemplate() + .getSpec() + .getContainers() + .get(0); + + var first = setUpRelativePath.apply("/"); + assertEquals("/health/ready", first.getReadinessProbe().getHttpGet().getPath()); + assertEquals("/health/live", first.getLivenessProbe().getHttpGet().getPath()); + + var second = setUpRelativePath.apply("some"); + assertEquals("some/health/ready", second.getReadinessProbe().getHttpGet().getPath()); + assertEquals("some/health/live", second.getLivenessProbe().getHttpGet().getPath()); + + var third = setUpRelativePath.apply(""); + assertEquals("/health/ready", third.getReadinessProbe().getHttpGet().getPath()); + assertEquals("/health/live", third.getLivenessProbe().getHttpGet().getPath()); + + var fourth = setUpRelativePath.apply("/some/"); + assertEquals("/some/health/ready", fourth.getReadinessProbe().getHttpGet().getPath()); + assertEquals("/some/health/live", fourth.getLivenessProbe().getHttpGet().getPath()); + } }