diff --git a/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java b/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java index 47cba6debd7ba..ce3fca30d6399 100644 --- a/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java +++ b/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java @@ -41,6 +41,7 @@ import io.quarkus.kubernetes.spi.KubernetesJobBuildItem; import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem; import io.quarkus.kubernetes.spi.KubernetesPortBuildItem; +import io.quarkus.kubernetes.spi.KubernetesProbePortNameBuildItem; import io.quarkus.kubernetes.spi.KubernetesResourceMetadataBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem; @@ -104,6 +105,7 @@ public List createDecorators(ApplicationInfoBuildItem applic Optional image, Optional command, List ports, + Optional portName, Optional livenessPath, Optional readinessPath, List roles, @@ -112,6 +114,7 @@ public List createDecorators(ApplicationInfoBuildItem applic return DevClusterHelper.createDecorators(KIND, applicationInfo, outputTarget, config, packageConfig, metricsConfiguration, initContainers, jobs, annotations, labels, envs, baseImage, image, command, ports, + portName, livenessPath, readinessPath, roles, roleBindings, customProjectRoot); diff --git a/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java b/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java index e2fc9e183e7c5..d1d34577a3c66 100644 --- a/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java +++ b/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java @@ -38,6 +38,7 @@ import io.quarkus.kubernetes.spi.KubernetesJobBuildItem; import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem; import io.quarkus.kubernetes.spi.KubernetesPortBuildItem; +import io.quarkus.kubernetes.spi.KubernetesProbePortNameBuildItem; import io.quarkus.kubernetes.spi.KubernetesResourceMetadataBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem; @@ -100,6 +101,7 @@ public List createDecorators(ApplicationInfoBuildItem applic Optional image, Optional command, List ports, + Optional portName, Optional livenessPath, Optional readinessPath, List roles, @@ -108,6 +110,7 @@ public List createDecorators(ApplicationInfoBuildItem applic return DevClusterHelper.createDecorators(MINIKUBE, applicationInfo, outputTarget, config, packageConfig, metricsConfiguration, initContainers, jobs, annotations, labels, envs, baseImage, image, command, ports, + portName, livenessPath, readinessPath, roles, roleBindings, customProjectRoot); 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 new file mode 100644 index 0000000000000..18b31fd7cced2 --- /dev/null +++ b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesProbePortNameBuildItem.java @@ -0,0 +1,19 @@ +package io.quarkus.kubernetes.spi; + +import io.quarkus.builder.item.SimpleBuildItem; + +/** + * A build item for selecting which port to use for probes using an {@literal HTTP get} action. + */ +public class KubernetesProbePortNameBuildItem extends SimpleBuildItem { + + private final String name; + + public KubernetesProbePortNameBuildItem(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyHttpGetActionPortDecorator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyHttpGetActionPortDecorator.java index 392539aeae077..eb4fa1b1e4ecf 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyHttpGetActionPortDecorator.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ApplyHttpGetActionPortDecorator.java @@ -1,33 +1,89 @@ - package io.quarkus.kubernetes.deployment; +import static io.dekorate.utils.Metadata.getMetadata; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + import io.dekorate.kubernetes.decorator.AddLivenessProbeDecorator; import io.dekorate.kubernetes.decorator.AddReadinessProbeDecorator; import io.dekorate.kubernetes.decorator.AddSidecarDecorator; -import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator; import io.dekorate.kubernetes.decorator.Decorator; import io.dekorate.kubernetes.decorator.ResourceProvidingDecorator; +import io.fabric8.kubernetes.api.builder.Builder; +import io.fabric8.kubernetes.api.model.ContainerBuilder; import io.fabric8.kubernetes.api.model.HTTPGetActionFluent; -public class ApplyHttpGetActionPortDecorator extends ApplicationContainerDecorator> { +public class ApplyHttpGetActionPortDecorator extends Decorator> { + private final String deployment; + private final String container; private final Integer port; + private final String probeKind; public ApplyHttpGetActionPortDecorator(Integer port) { - this(ANY, ANY, port); + this(ANY, ANY, port, ANY); + } + + public ApplyHttpGetActionPortDecorator(Integer port, String probeKind) { + this(ANY, ANY, port, probeKind); } public ApplyHttpGetActionPortDecorator(String deployment, Integer port) { - this(deployment, ANY, port); + this(deployment, ANY, port, ANY); + } + + public ApplyHttpGetActionPortDecorator(String deployment, Integer port, String probeKind) { + this(deployment, ANY, port, probeKind); } public ApplyHttpGetActionPortDecorator(String deployment, String container, Integer port) { - super(deployment, container); + this(deployment, container, port, ANY); + } + + public ApplyHttpGetActionPortDecorator(String deployment, String container, Integer port, String probeKind) { + this.deployment = deployment; + this.container = container; this.port = port; + this.probeKind = probeKind; + } + + @Override + public void visit(List> path, HTTPGetActionFluent action) { + boolean inMatchingProbe = probeKind == ANY || path.stream().map(e -> e.getKey()).anyMatch(i -> i.equals(probeKind)); + if (!inMatchingProbe) { + return; + } + + boolean inMatchingContainer = container == ANY || path.stream() + .map(e -> e.getValue()) + .filter(v -> v instanceof ContainerBuilder) + .map(v -> (ContainerBuilder) v) + .anyMatch(c -> c.getName() != null && c.getName().equals(container)); + + if (!inMatchingContainer) { + return; + } + + boolean inMatchingResource = deployment == ANY || path.stream() + .map(e -> e.getValue()) + .filter(v -> v instanceof Builder) + .map(v -> (Builder) v) + .map(b -> getMetadata(b)) + .filter(m -> m.isPresent()) + .map(Optional::get) + .anyMatch(m -> m.getName() != null && m.getName().equals(deployment)); + + if (!inMatchingResource) { + return; + } + + visit(action); } @Override - public void andThenVisit(HTTPGetActionFluent action) { + public void visit(HTTPGetActionFluent action) { if (port == null) { // workaround to make sure we don't get a NPE action.withNewPort((String) null); diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ChangeDeploymentTriggerDecorator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ChangeDeploymentTriggerDecorator.java index badd3dd41eb38..8edf073f00e13 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ChangeDeploymentTriggerDecorator.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/ChangeDeploymentTriggerDecorator.java @@ -13,4 +13,5 @@ public ChangeDeploymentTriggerDecorator(String containerName, String imageStream public Class[] after() { return new Class[] { ApplyDeploymentTriggerDecorator.class, RemoveDeploymentTriggerDecorator.class }; } + } 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 a31cb79ff4d74..a7c7c44c2d0dd 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 @@ -1,7 +1,6 @@ package io.quarkus.kubernetes.deployment; -import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT; import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES; import static io.quarkus.kubernetes.deployment.Constants.MAX_NODE_PORT_VALUE; import static io.quarkus.kubernetes.deployment.Constants.MAX_PORT_NUMBER; @@ -42,6 +41,7 @@ import io.quarkus.kubernetes.spi.KubernetesJobBuildItem; import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem; import io.quarkus.kubernetes.spi.KubernetesPortBuildItem; +import io.quarkus.kubernetes.spi.KubernetesProbePortNameBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem; @@ -64,6 +64,7 @@ public static List createDecorators(String clusterKind, Optional image, Optional command, List ports, + Optional portName, Optional livenessPath, Optional readinessPath, List roles, @@ -118,8 +119,14 @@ public static List createDecorators(String clusterKind, } //Probe port handling - Integer portNumber = port.map(Port::getContainerPort).orElse(DEFAULT_HTTP_PORT); - result.add(new DecoratorBuildItem(clusterKind, new ApplyHttpGetActionPortDecorator(name, name, portNumber))); + result.add( + KubernetesCommonHelper.createProbeHttpPortDecorator(name, clusterKind, "livenessProbe", config.livenessProbe, + portName, + ports)); + result.add( + KubernetesCommonHelper.createProbeHttpPortDecorator(name, clusterKind, "readinessProbe", config.readinessProbe, + portName, + 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/KnativeProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java index f5490ee727224..d4d3029bf28c4 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java @@ -282,7 +282,7 @@ public List createDecorators(ApplicationInfoBuildItem applic result.add(new DecoratorBuildItem(KNATIVE, new ApplyServiceTypeDecorator(name, config.getServiceType().name()))); //In Knative its expected that all http ports in probe are omitted (so we set them to null). - result.add(new DecoratorBuildItem(KNATIVE, new ApplyHttpGetActionPortDecorator(name, null))); + result.add(new DecoratorBuildItem(KNATIVE, new ApplyHttpGetActionPortDecorator(name, (Integer) null))); //Traffic Splitting config.revisionName.ifPresent(r -> { 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 9f6838391ae96..959864deab4c1 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 @@ -2,6 +2,8 @@ package io.quarkus.kubernetes.deployment; import static io.dekorate.kubernetes.decorator.AddServiceResourceDecorator.distinct; +import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT; +import static io.quarkus.kubernetes.deployment.Constants.HTTP_PORT; import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_BUILD_TIMESTAMP; import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_COMMIT_ID; import static io.quarkus.kubernetes.deployment.Constants.QUARKUS_ANNOTATIONS_VCS_URL; @@ -81,6 +83,7 @@ import io.quarkus.kubernetes.spi.KubernetesJobBuildItem; import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem; import io.quarkus.kubernetes.spi.KubernetesPortBuildItem; +import io.quarkus.kubernetes.spi.KubernetesProbePortNameBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem; @@ -687,6 +690,46 @@ private static List createAnnotationDecorators(Optional portName, + List ports) { + + //1. check if `httpActionPort` is defined + //2. lookup port by `httpPortName` + //3. fallback to DEFAULT_HTTP_PORT + String httpPortName = probeConfig.httpActionPortName + .or(() -> portName.map(KubernetesProbePortNameBuildItem::getName)) + .orElse(HTTP_PORT); + + 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)); + } + + /** + * Create the decorators needed for setting up probes. + * The method will not create decorators related to ports, as they are not supported by all targets (e.g. knative) + * Port related decorators are created by `applyProbePort` instead. + * + * @return a list of decorators that configure the probes + */ private static List createProbeDecorators(String name, String target, ProbeConfig livenessProbe, ProbeConfig readinessProbe, Optional livenessPath, 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 d73924830a867..ffe3064fd6672 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 @@ -1,7 +1,6 @@ package io.quarkus.kubernetes.deployment; -import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT; import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_S2I_IMAGE_NAME; import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT; import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT_APP_RUNTIME; @@ -61,6 +60,7 @@ import io.quarkus.kubernetes.spi.KubernetesJobBuildItem; import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem; import io.quarkus.kubernetes.spi.KubernetesPortBuildItem; +import io.quarkus.kubernetes.spi.KubernetesProbePortNameBuildItem; import io.quarkus.kubernetes.spi.KubernetesResourceMetadataBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem; @@ -179,6 +179,7 @@ public List createDecorators(ApplicationInfoBuildItem applic Optional baseImage, Optional image, Optional command, + Optional portName, List ports, Optional livenessPath, Optional readinessPath, @@ -301,8 +302,13 @@ public List createDecorators(ApplicationInfoBuildItem applic } // Probe port handling - Integer portNumber = port.map(Port::getContainerPort).orElse(DEFAULT_HTTP_PORT); - result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyHttpGetActionPortDecorator(name, name, portNumber))); + result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, "livenssProbe", config.livenessProbe, + portName, + ports)); + result.add( + KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, "readinessProbe", config.readinessProbe, + portName, + ports)); // Handle non-openshift builds if (deploymentKind == DeploymentResourceKind.DeploymentConfig 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 4bfa91d166a87..4efdbf7543e75 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 @@ -10,6 +10,19 @@ @ConfigGroup public class ProbeConfig { + /** + * The port number to use when configuring the {@literal http get} action. + * If not configured, the port corresponding to the {@code httpActionPortName} will be used. + */ + @ConfigItem + Optional httpActionPort; + + /** + * The port name for selecting the port of the {@literal HTTP get} action. + */ + @ConfigItem + Optional httpActionPortName; + /** * The http path to use for the probe For this to work, the container port also * needs to be set. 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 682e806001a56..6119ea9c0ff44 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 @@ -1,7 +1,6 @@ package io.quarkus.kubernetes.deployment; -import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT; import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT_GROUP; import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT_VERSION; import static io.quarkus.kubernetes.deployment.Constants.INGRESS; @@ -52,6 +51,7 @@ import io.quarkus.kubernetes.spi.KubernetesJobBuildItem; import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem; import io.quarkus.kubernetes.spi.KubernetesPortBuildItem; +import io.quarkus.kubernetes.spi.KubernetesProbePortNameBuildItem; import io.quarkus.kubernetes.spi.KubernetesResourceMetadataBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem; @@ -132,6 +132,7 @@ public List createDecorators(ApplicationInfoBuildItem applic List annotations, List labels, List envs, Optional image, Optional command, + Optional portName, List ports, Optional livenessPath, Optional readinessPath, List roles, List roleBindings, Optional customProjectRoot, @@ -241,8 +242,14 @@ public List createDecorators(ApplicationInfoBuildItem applic } // Probe port handling - Integer portNumber = port.map(Port::getContainerPort).orElse(DEFAULT_HTTP_PORT); - result.add(new DecoratorBuildItem(KUBERNETES, new ApplyHttpGetActionPortDecorator(name, name, portNumber))); + result.add( + KubernetesCommonHelper.createProbeHttpPortDecorator(name, KUBERNETES, "livenessProbe", config.livenessProbe, + portName, + ports)); + result.add( + KubernetesCommonHelper.createProbeHttpPortDecorator(name, KUBERNETES, "readinessProbe", config.readinessProbe, + portName, + ports)); // Handle remote debug configuration if (config.remoteDebug.enabled) { @@ -274,5 +281,4 @@ void externalizeInitTasks( decorators); } } - } diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithProbePortTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithProbePortTest.java new file mode 100644 index 0000000000000..07a25a2bf1a7f --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithProbePortTest.java @@ -0,0 +1,65 @@ +package io.quarkus.it.kubernetes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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.apps.Deployment; +import io.quarkus.builder.Version; +import io.quarkus.maven.dependency.Dependency; +import io.quarkus.test.ProdBuildResults; +import io.quarkus.test.ProdModeTestResults; +import io.quarkus.test.QuarkusProdModeTest; + +public class KubernetesWithProbePortTest { + + @RegisterExtension + static final QuarkusProdModeTest config = new QuarkusProdModeTest() + .withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class)) + .setApplicationName("kubernetes-with-probe-port") + .setApplicationVersion("0.1-SNAPSHOT") + .overrideConfigKey("quarkus.kubernetes.readiness-probe.http-action-port", "9191") + .setLogFileName("k8s.log") + .setForcedDependencies(List.of( + Dependency.of("io.quarkus", "quarkus-kubernetes", Version.getVersion()), + Dependency.of("io.quarkus", "quarkus-smallrye-health", Version.getVersion()))); + + @ProdBuildResults + private ProdModeTestResults prodModeTestResults; + + @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("kubernetes-with-probe-port"); + }); + + 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 -> { + assertEquals(p.getHttpGet().getPort().getIntVal(), 9191); + }); + }); + }); + }); + }); + }); + } +}