From 222933c0091de5aac0efe448a6afb9c871369cf5 Mon Sep 17 00:00:00 2001 From: Jose Date: Mon, 15 May 2023 09:37:10 +0200 Subject: [PATCH] Fix K8s/OpenShift deployment when using management interface+https Note that these changes will move the management ssl configuration to built-time configuration. Moreover, the logic to select the HTTPS schema mimics to the logic in VertxHttpRecorder.initializeMainHttpServer method. Fix https://github.com/quarkusio/quarkus/issues/32225 --- .../spi/KubernetesProbePortNameBuildItem.java | 10 ++ .../deployment/DevClusterHelper.java | 9 +- .../deployment/KubernetesCommonHelper.java | 26 ++++- .../deployment/OpenshiftProcessor.java | 19 ++-- .../kubernetes/deployment/PortConfig.java | 6 ++ .../kubernetes/deployment/ProbeConfig.java | 6 ++ .../VanillaKubernetesProcessor.java | 9 +- .../deployment/SmallRyeHealthProcessor.java | 26 ++++- ...ithHealthUsingManagementInterfaceTest.java | 14 ++- ...curedManagementInterfaceAtRuntimeTest.java | 88 ++++++++++++++++ ...thUsingSecuredManagementInterfaceTest.java | 97 ++++++++++++++++++ ...d-secured-management-at-runtime.properties | 5 + ...h-health-and-secured-management.properties | 6 ++ .../server.keystore | Bin 0 -> 2407 bytes 14 files changed, 298 insertions(+), 23 deletions(-) create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceAtRuntimeTest.java create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceTest.java create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management-at-runtime.properties create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management.properties create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/resources/manifests/kubernetes-with-health-and-secured-management/server.keystore diff --git a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesProbePortNameBuildItem.java b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesProbePortNameBuildItem.java index cfb1f92a2e556c..c88174d1481331 100644 --- a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesProbePortNameBuildItem.java +++ b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesProbePortNameBuildItem.java @@ -8,12 +8,22 @@ public final class KubernetesProbePortNameBuildItem extends SimpleBuildItem { private final String name; + private final String schema; public KubernetesProbePortNameBuildItem(String name) { + this(name, null); + } + + public KubernetesProbePortNameBuildItem(String name, String schema) { this.name = name; + this.schema = schema; } public String getName() { return name; } + + public String getSchema() { + return schema; + } } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java index 77bc359390b6bf..a0987cf2d24e80 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java @@ -133,15 +133,18 @@ public static List createDecorators(String clusterKind, result.add( KubernetesCommonHelper.createProbeHttpPortDecorator(name, clusterKind, LIVENESS_PROBE, config.livenessProbe, portName, - ports)); + ports, + config.ports)); result.add( KubernetesCommonHelper.createProbeHttpPortDecorator(name, clusterKind, READINESS_PROBE, config.readinessProbe, portName, - ports)); + ports, + config.ports)); result.add( KubernetesCommonHelper.createProbeHttpPortDecorator(name, clusterKind, STARTUP_PROBE, config.startupProbe, portName, - ports)); + ports, + config.ports)); // Handle init Containers result.addAll(KubernetesCommonHelper.createInitContainerDecorators(clusterKind, name, initContainers, result)); diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java index 591ae9947c4a38..4fd145455bc26c 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java @@ -107,6 +107,8 @@ public class KubernetesCommonHelper { "Deployment", "DeploymentConfig" }; private static final String DEFAULT_ROLE_NAME_VIEW = "view"; private static final List LIST_WITH_EMPTY = List.of(""); + private static final String SCHEMA_HTTP = "HTTP"; + private static final String SCHEMA_HTTPS = "HTTPS"; public static Optional createProject(ApplicationInfoBuildItem app, Optional customProjectRoot, OutputTargetBuildItem outputTarget, @@ -946,7 +948,8 @@ private static List createAnnotationDecorators(Optional portName, - List ports) { + List ports, + Map portsFromConfig) { //1. check if `httpActionPort` is defined //2. lookup port by `httpPortName` @@ -958,7 +961,26 @@ public static DecoratorBuildItem createProbeHttpPortDecorator(String name, Strin Integer port = probeConfig.httpActionPort .orElse(ports.stream().filter(p -> httpPortName.equals(p.getName())) .map(KubernetesPortBuildItem::getPort).findFirst().orElse(DEFAULT_HTTP_PORT)); - return new DecoratorBuildItem(target, new ApplyHttpGetActionPortDecorator(name, name, port, probeKind)); + + // Resolve schema property from: + String schema; + if (probeConfig.httpActionSchema.isPresent()) { + // 1. User in Probe config + schema = probeConfig.httpActionSchema.get(); + } else if (portsFromConfig.containsKey(httpPortName) && portsFromConfig.get(httpPortName).tls) { + // 2. User in Ports config + schema = SCHEMA_HTTPS; + } else if (portName.isPresent() + && portName.get().getSchema() != null + && portName.get().getName().equals(httpPortName)) { + // 3. Extensions + schema = portName.get().getSchema(); + } else { + // 4. Using the port number. + schema = port != null && (port == 443 || port == 8443) ? SCHEMA_HTTPS : SCHEMA_HTTP; + } + + return new DecoratorBuildItem(target, new ApplyHttpGetActionPortDecorator(name, name, port, probeKind, schema)); } /** diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java index 1f180f8d31bf17..c0635846362e33 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java @@ -322,15 +322,16 @@ public List createDecorators(ApplicationInfoBuildItem applic // Probe port handling result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, LIVENESS_PROBE, config.livenessProbe, portName, - ports)); - result.add( - KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, READINESS_PROBE, config.readinessProbe, - portName, - ports)); - result.add( - KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, STARTUP_PROBE, config.startupProbe, - portName, - ports)); + ports, + config.ports)); + result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, READINESS_PROBE, config.readinessProbe, + portName, + ports, + config.ports)); + result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, STARTUP_PROBE, config.startupProbe, + portName, + ports, + config.ports)); // Handle non-openshift builds if (deploymentKind == DeploymentResourceKind.DeploymentConfig diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PortConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PortConfig.java index 0a431297b3b792..5eb43205f0c7ed 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PortConfig.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PortConfig.java @@ -43,4 +43,10 @@ public class PortConfig { */ public OptionalInt nodePort; + /** + * If enabled, the port will be configured to use the schema HTTPS. + */ + @ConfigItem(defaultValue = "false") + public boolean tls; + } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ProbeConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ProbeConfig.java index b186b82da956c1..599f019d2efa6b 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ProbeConfig.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ProbeConfig.java @@ -36,6 +36,12 @@ public class ProbeConfig { @ConfigItem Optional httpActionPath; + /** + * The schema of the {@literal HTTP get} action. Can be either "HTTP" or "HTTPS". + */ + @ConfigItem + Optional httpActionSchema; + /** * The command to use for the probe. */ diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java index ca88fe0eff3ecb..b2358f9ca645d4 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java @@ -257,15 +257,18 @@ public List createDecorators(ApplicationInfoBuildItem applic result.add( KubernetesCommonHelper.createProbeHttpPortDecorator(name, KUBERNETES, LIVENESS_PROBE, config.livenessProbe, portName, - ports)); + ports, + config.ports)); result.add( KubernetesCommonHelper.createProbeHttpPortDecorator(name, KUBERNETES, READINESS_PROBE, config.readinessProbe, portName, - ports)); + ports, + config.ports)); result.add( KubernetesCommonHelper.createProbeHttpPortDecorator(name, KUBERNETES, STARTUP_PROBE, config.startupProbe, portName, - ports)); + ports, + config.ports)); // Handle remote debug configuration if (config.remoteDebug.enabled) { diff --git a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java index 26f570bb4b7000..6f9aea794144da 100644 --- a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java +++ b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java @@ -7,11 +7,13 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.function.BooleanSupplier; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.health.Liveness; import org.eclipse.microprofile.health.Readiness; @@ -102,6 +104,15 @@ class SmallRyeHealthProcessor { private static final String BRANDING_FAVICON_GENERAL = BRANDING_DIR + "favicon.ico"; private static final String BRANDING_FAVICON_MODULE = BRANDING_DIR + "smallrye-health-ui.ico"; + // For Kubernetes exposing + private static final String SCHEMA_HTTP = "HTTP"; + private static final String SCHEMA_HTTPS = "HTTPS"; + + // For Management ports + private static final String MANAGEMENT_SSL_PREFIX = "quarkus.management.ssl.certificate."; + private static final List MANAGEMENT_SSL_PROPERTIES = List.of("key-store-file", "trust-store-file", "files", + "key-files"); + static class OpenAPIIncluded implements BooleanSupplier { HealthBuildTimeConfig config; @@ -344,7 +355,7 @@ public void kubernetes(NonApplicationRootPathBuildItem nonApplicationRootPathBui if (managementInterfaceBuildTimeConfig.enabled) { // Switch to the "management" port - port.produce(new KubernetesProbePortNameBuildItem("management")); + port.produce(new KubernetesProbePortNameBuildItem("management", selectSchemaForManagement())); } livenessPathItemProducer.produce( @@ -466,4 +477,17 @@ public String updateApiUrl(String original, String healthPath) { private static boolean shouldInclude(LaunchModeBuildItem launchMode, SmallRyeHealthConfig healthConfig) { return launchMode.getLaunchMode().isDevOrTest() || healthConfig.ui.alwaysInclude; } + + private static String selectSchemaForManagement() { + Config config = ConfigProvider.getConfig(); + for (String sslProperty : MANAGEMENT_SSL_PROPERTIES) { + Optional> property = config.getOptionalValues(MANAGEMENT_SSL_PREFIX + sslProperty, + String.class); + if (property.isPresent()) { + return SCHEMA_HTTPS; + } + } + + return SCHEMA_HTTP; + } } diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingManagementInterfaceTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingManagementInterfaceTest.java index 27c8667af19081..11d6f0f4d3fb8a 100644 --- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingManagementInterfaceTest.java +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingManagementInterfaceTest.java @@ -25,14 +25,16 @@ public class KubernetesWithHealthUsingManagementInterfaceTest { + private static final String NAME = "kubernetes-with-health-and-management"; + @RegisterExtension static final QuarkusProdModeTest config = new QuarkusProdModeTest() .withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class)) - .setApplicationName("health") + .setApplicationName(NAME) .setApplicationVersion("0.1-SNAPSHOT") .setRun(true) .setLogFileName("k8s.log") - .withConfigurationResource("kubernetes-with-health-and-management.properties") + .withConfigurationResource(NAME + ".properties") .setForcedDependencies(List.of( Dependency.of("io.quarkus", "quarkus-smallrye-health", Version.getVersion()))); @@ -64,7 +66,7 @@ public void assertGeneratedResources() throws IOException { .deserializeAsList(kubernetesDir.resolve("kubernetes.yml")); assertThat(kubernetesList.get(0)).isInstanceOfSatisfying(Deployment.class, d -> { assertThat(d.getMetadata()).satisfies(m -> { - assertThat(m.getName()).isEqualTo("health"); + assertThat(m.getName()).isEqualTo(NAME); }); assertThat(d.getSpec()).satisfies(deploymentSpec -> { @@ -76,14 +78,16 @@ public void assertGeneratedResources() throws IOException { assertProbePath(p, "/q/health/ready"); assertNotNull(p.getHttpGet()); - assertEquals(p.getHttpGet().getPort().getIntVal(), 9000); + assertEquals("HTTP", p.getHttpGet().getScheme()); + assertEquals(9000, p.getHttpGet().getPort().getIntVal()); }); assertThat(container.getLivenessProbe()).isNotNull().satisfies(p -> { assertThat(p.getInitialDelaySeconds()).isEqualTo(20); assertProbePath(p, "/liveness"); assertNotNull(p.getHttpGet()); - assertEquals(p.getHttpGet().getPort().getIntVal(), 9000); + assertEquals("HTTP", p.getHttpGet().getScheme()); + assertEquals(9000, p.getHttpGet().getPort().getIntVal()); }); }); }); diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceAtRuntimeTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceAtRuntimeTest.java new file mode 100644 index 00000000000000..006136fca6dd1d --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceAtRuntimeTest.java @@ -0,0 +1,88 @@ +package io.quarkus.it.kubernetes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Probe; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.quarkus.builder.Version; +import io.quarkus.maven.dependency.Dependency; +import io.quarkus.test.LogFile; +import io.quarkus.test.ProdBuildResults; +import io.quarkus.test.ProdModeTestResults; +import io.quarkus.test.QuarkusProdModeTest; + +public class KubernetesWithHealthUsingSecuredManagementInterfaceAtRuntimeTest { + + private static final String NAME = "kubernetes-with-health-and-secured-management-at-runtime"; + + @RegisterExtension + static final QuarkusProdModeTest config = new QuarkusProdModeTest() + .withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class)) + .setApplicationName(NAME) + .setApplicationVersion("0.1-SNAPSHOT") + .withConfigurationResource(NAME + ".properties") + .setForcedDependencies(List.of( + Dependency.of("io.quarkus", "quarkus-smallrye-health", Version.getVersion()))); + + @ProdBuildResults + private ProdModeTestResults prodModeTestResults; + + @LogFile + private Path logfile; + + @Test + public void assertGeneratedResources() throws IOException { + final Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes"); + assertThat(kubernetesDir) + .isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.json")) + .isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.yml")); + List kubernetesList = DeserializationUtil + .deserializeAsList(kubernetesDir.resolve("kubernetes.yml")); + assertThat(kubernetesList.get(0)).isInstanceOfSatisfying(Deployment.class, d -> { + assertThat(d.getMetadata()).satisfies(m -> { + assertThat(m.getName()).isEqualTo(NAME); + }); + + assertThat(d.getSpec()).satisfies(deploymentSpec -> { + assertThat(deploymentSpec.getTemplate()).satisfies(t -> { + assertThat(t.getSpec()).satisfies(podSpec -> { + assertThat(podSpec.getContainers()).singleElement().satisfies(container -> { + assertThat(container.getReadinessProbe()).isNotNull().satisfies(p -> { + assertThat(p.getInitialDelaySeconds()).isEqualTo(5); + assertProbePath(p, "/q/health/ready"); + + assertNotNull(p.getHttpGet()); + assertEquals("HTTPS", p.getHttpGet().getScheme()); + assertEquals(9000, p.getHttpGet().getPort().getIntVal()); + }); + assertThat(container.getLivenessProbe()).isNotNull().satisfies(p -> { + assertThat(p.getInitialDelaySeconds()).isEqualTo(20); + assertProbePath(p, "/liveness"); + + assertNotNull(p.getHttpGet()); + assertEquals("HTTPS", p.getHttpGet().getScheme()); + assertEquals(9000, p.getHttpGet().getPort().getIntVal()); + }); + }); + }); + }); + }); + }); + } + + private void assertProbePath(Probe p, String expectedPath) { + assertThat(p.getHttpGet()).satisfies(h -> { + assertThat(h.getPath()).isEqualTo(expectedPath); + }); + } +} diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceTest.java new file mode 100644 index 00000000000000..75a16e3dd193b9 --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithHealthUsingSecuredManagementInterfaceTest.java @@ -0,0 +1,97 @@ +package io.quarkus.it.kubernetes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Probe; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.quarkus.builder.Version; +import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; +import io.quarkus.maven.dependency.Dependency; +import io.quarkus.test.LogFile; +import io.quarkus.test.ProdBuildResults; +import io.quarkus.test.ProdModeTestResults; +import io.quarkus.test.QuarkusProdModeTest; + +public class KubernetesWithHealthUsingSecuredManagementInterfaceTest { + + private static final String NAME = "kubernetes-with-health-and-secured-management"; + + @RegisterExtension + static final QuarkusProdModeTest config = new QuarkusProdModeTest() + .withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class)) + .setApplicationName(NAME) + .setApplicationVersion("0.1-SNAPSHOT") + .addCustomResourceEntry(Path.of("src", "main", "resources", "META-INF", "server.keystore"), + "manifests/" + NAME + "/server.keystore") + .setLogFileName("k8s.log") + .withConfigurationResource(NAME + ".properties") + .setForcedDependencies(List.of( + Dependency.of("io.quarkus", "quarkus-smallrye-health", Version.getVersion()))) + .addBuildChainCustomizerEntries( + new QuarkusProdModeTest.BuildChainCustomizerEntry( + OpenshiftWithCommonResourcesTest.CustomProjectRootBuildItemProducerProdMode.class, + Collections.singletonList(CustomProjectRootBuildItem.class), Collections.emptyList())); + + @ProdBuildResults + private ProdModeTestResults prodModeTestResults; + + @LogFile + private Path logfile; + + @Test + public void assertGeneratedResources() throws IOException { + final Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes"); + assertThat(kubernetesDir) + .isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.json")) + .isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.yml")); + List kubernetesList = DeserializationUtil + .deserializeAsList(kubernetesDir.resolve("kubernetes.yml")); + assertThat(kubernetesList.get(0)).isInstanceOfSatisfying(Deployment.class, d -> { + assertThat(d.getMetadata()).satisfies(m -> { + assertThat(m.getName()).isEqualTo(NAME); + }); + + assertThat(d.getSpec()).satisfies(deploymentSpec -> { + assertThat(deploymentSpec.getTemplate()).satisfies(t -> { + assertThat(t.getSpec()).satisfies(podSpec -> { + assertThat(podSpec.getContainers()).singleElement().satisfies(container -> { + assertThat(container.getReadinessProbe()).isNotNull().satisfies(p -> { + assertThat(p.getInitialDelaySeconds()).isEqualTo(5); + assertProbePath(p, "/q/health/ready"); + + assertNotNull(p.getHttpGet()); + assertEquals("HTTPS", p.getHttpGet().getScheme()); + assertEquals(9000, p.getHttpGet().getPort().getIntVal()); + }); + assertThat(container.getLivenessProbe()).isNotNull().satisfies(p -> { + assertThat(p.getInitialDelaySeconds()).isEqualTo(20); + assertProbePath(p, "/liveness"); + + assertNotNull(p.getHttpGet()); + assertEquals("HTTPS", p.getHttpGet().getScheme()); + assertEquals(9000, p.getHttpGet().getPort().getIntVal()); + }); + }); + }); + }); + }); + }); + } + + private void assertProbePath(Probe p, String expectedPath) { + assertThat(p.getHttpGet()).satisfies(h -> { + assertThat(h.getPath()).isEqualTo(expectedPath); + }); + } +} diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management-at-runtime.properties b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management-at-runtime.properties new file mode 100644 index 00000000000000..73f9a5789a344f --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management-at-runtime.properties @@ -0,0 +1,5 @@ +quarkus.http.port=9090 +quarkus.management.enabled=true +quarkus.kubernetes.liveness-probe.initial-delay=20s +quarkus.kubernetes.ports.management.tls=true +quarkus.smallrye-health.liveness-path=/liveness diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management.properties b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management.properties new file mode 100644 index 00000000000000..babd27dab5e473 --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/kubernetes-with-health-and-secured-management.properties @@ -0,0 +1,6 @@ +quarkus.http.port=9090 +quarkus.management.enabled=true +quarkus.management.ssl.certificate.key-store-file=META-INF/server.keystore +quarkus.management.ssl.certificate.key-store-password=password +quarkus.kubernetes.liveness-probe.initial-delay=20s +quarkus.smallrye-health.liveness-path=/liveness diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/manifests/kubernetes-with-health-and-secured-management/server.keystore b/integration-tests/kubernetes/quarkus-standard-way/src/test/resources/manifests/kubernetes-with-health-and-secured-management/server.keystore new file mode 100644 index 0000000000000000000000000000000000000000..cdef1caf3c6da29b3dfff68f816ecd0171727dbf GIT binary patch literal 2407 zcmY+EX*d)L7stn#8OD-*3_}=OXv~bA8e|%~OR`4EPEiVpFiaS^Mp4OnQI?E5wn8Ja zX1OBS*BFGkV~MN@Z})xP_ul7zIOjai?|;tu_`{H(o`ak~p903x( zGl05=yRmd*Gp>W~N}RCU*j@peu_J#<>?zJD+15MH-1Jsa@ByP4IA)-dF-pzBspX z98Mv|&(NP7%&wF8%3@0<5c*Q4QnlMLi@$z!?xd#Ma%>i3p*hO)AnJSub#QYobQh2~ z7ApM=p&?g8*`8}GQ~G5RP3Y11H6V)7Vjo47luePUYGvp-rKBb&$7koL`F0R!NBe~2 zPrr9x3pWyXFfnqeHjz(tLQb1IEOpbex)W!i@2#x4Y;I9}GLEf#Nl zZih>2E{u@YUd#uS^$)U#$sf60PLxm%RT7 z{Y=;remnSQ#KISw9k+^RYfg<5`+1fn*|8jJ&mZkI;LJh8L3*d-F&{J0rdNoPPjtbF z;A`_J`LW9mgIjlv-v-o#QoUMz1Wv)&O>GR6)d~@U3e#_Q*k4&cNZIv6iXVv%>V4yr zZcFR1y2=_937LOi`r^)RY9>+7)x1gl*b+C;+`4s8qOEv1Qz61s{w8L!UO;_{VV*5? z8-ip8bchVBAC1r?{LYvp<@ng2C>=JaSyT^?;K(U#Q0F6>%IpGe6&R@226wJ%*~XfB zOR@JS&vV~=OofU28WuU`YI+9oi{1)`DdK0tY+3v@_Vjt}=2^7!PL&ed><3)0_Vi7! z_z5PYg*+j#kQ-c29!)l$%A2FZV27$Sh1%1%3Aati@TdplB`zAMT9*^0x2A*XfPM)-PiWWuMe`b4OVoER!w&>cRfk_qNlR7 zH;h}nP+i$6(sg@ceNfwG7WGpx?J9Y3NHre(mPt<`mY0neL^p!xo}cUUjyz_(8H=AC zxKuz^Epo&Olu~Smpy9RV277=+1DajJu3pls#n3A*5VtTHX`$@S&`pf~_ zvQ%~2ih_r(p60P5)~7BrfU=2r&x7`bM4oe&m{cSShtm zQF15TL%`);PJ1kH$urU%VG}*qkCYW(I&`=+f ze;c?1C%F4(Mbt&&@;c{HD(8IXJ5iwvdhmxFKGm~{=^#KN-NBRwwxmL!B+>dNgQ zSVIirZ&gBtu_sRQ0D=MDfZKpOe|3z^KcNU#7$j)tALuQO)xv1&YGW{3nwpwg7!v!F zzn3^5`6TxEpC}f{2KYH5{z=&WWmw2xhNbxEkFu92TyT=-hMsbnU7uXj(EqPtV@T|V z^dU1BrlP__h7lF%BI6+^FKfM~!mlFVhnR7y>E~fe4kb0MRu+GB4ln5+k58Hyh_n^x zAAZc$kJgCr{4oKQ#}rhHoHc{i@;WdEodxSBb29vN$lT$udVV(!)EnR;nRz9nRH@Mz z(M3y&=vh=<_j2#mHkeL|%KI2+p|wZJ@O-HpvsQkkO8e2{*YwqqR{5yJb;9Nj9}>5O z|J<5L8^T64=S9d^HWf~By7>_+bOqw}w1t-$22Q=Y6 zA$_RFa1~J|RTCcKjy<1%5d1TZMQO=ni)oR8O9gImb188iQjUsV&p;1$@f#Dlk|nYZ z(bZ?K7|?0K=I~WbE_p6{I!`rpt=hc;riglQrHg-JOxGt@h%<)p^>zXqtKi5zu zD$poUvufFaw>n*U^t{+KmH*Txb%OG1x=H&z_m5yp5~)om5V3b%x9jV(wd-A`{FY8ttiy_#I>UVR&>t7K^tM;_1yE?59Uy(n zWGG#GG+5sTvJ$MGv7;b%S(Y|Zq|<;wzj;+lRvGeSqOe|53iSgvup*K35HM8VcX<;p^XmPZ}jWHI^} z84MHxRyn~A6bA!9!oxkh8y?8tzwn!7iwge!p-i~XbsHq?`qUS#CFl3(DiX7ghgeh& NtHU8ccD984{{ZbYXC(jt literal 0 HcmV?d00001