Skip to content

Commit

Permalink
feat: allow configuring port of http probes
Browse files Browse the repository at this point in the history
  • Loading branch information
iocanel committed Jan 24, 2023
1 parent cd3bb03 commit 664ce65
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

package io.quarkus.kubernetes.deployment;

import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_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;
Expand Down Expand Up @@ -669,6 +670,28 @@ private static List<DecoratorBuildItem> createAnnotationDecorators(Optional<Proj
return result;
}

/**
* @return a decorator for configures the port of the http action of the probe.
*/
public static DecoratorBuildItem createProbeHttpPortDecorator(String name, String target, ProbeConfig probeConfig,
List<KubernetesPortBuildItem> ports) {

//1. check if `httpActionPort` is defined
//2. lookup port by `httpPortName`
//3. fallback to DEFAULT_HTTP_PORT
Integer port = probeConfig.httpActionPort
.orElse(ports.stream().filter(p -> probeConfig.httpActionPortName.equals(p.getName()))
.map(KubernetesPortBuildItem::getPort).findFirst().orElse(DEFAULT_HTTP_PORT));
return new DecoratorBuildItem(target, new ApplyHttpGetActionPortDecorator(name, name, port));
}

/**
* 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<DecoratorBuildItem> createProbeDecorators(String name, String target, ProbeConfig livenessProbe,
ProbeConfig readinessProbe,
Optional<KubernetesHealthLivenessPathBuildItem> livenessPath,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@

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.HTTP_PORT;
import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT;
import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT_APP_RUNTIME;
import static io.quarkus.kubernetes.deployment.Constants.QUARKUS;
Expand Down Expand Up @@ -298,9 +296,8 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
}

// Probe port handling
Integer port = ports.stream().filter(p -> HTTP_PORT.equals(p.getName())).map(KubernetesPortBuildItem::getPort)
.findFirst().orElse(DEFAULT_HTTP_PORT);
result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyHttpGetActionPortDecorator(name, name, port)));
result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, config.livenessProbe, ports));
result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, OPENSHIFT, config.readinessProbe, ports));

// Handle non-openshift builds
if (deploymentKind == DeploymentResourceKind.DeploymentConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
@ConfigGroup
public class ProbeConfig {

/**
* The port number to use when configuring the http get.
* If not configured the port that corresponds to the `httpActionPortName` will be used.
*/
@ConfigItem
Optional<Integer> httpActionPort;

/**
* The port name ot use for selecting the port to congiure for the http get.
*/
@ConfigItem(defaultValue = "http")
String httpActionPortName;

/**
* The http path to use for the probe For this to work, the container port also
* needs to be set.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +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.DEPLOYMENT_GROUP;
import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT_VERSION;
import static io.quarkus.kubernetes.deployment.Constants.HTTP_PORT;
import static io.quarkus.kubernetes.deployment.Constants.INGRESS;
import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES;
import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.VANILLA_KUBERNETES_PRIORITY;
Expand Down Expand Up @@ -246,9 +244,8 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
}

// Probe port handling
Integer port = ports.stream().filter(p -> HTTP_PORT.equals(p.getName())).map(KubernetesPortBuildItem::getPort)
.findFirst().orElse(DEFAULT_HTTP_PORT);
result.add(new DecoratorBuildItem(KUBERNETES, new ApplyHttpGetActionPortDecorator(name, name, port)));
result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, KUBERNETES, config.livenessProbe, ports));
result.add(KubernetesCommonHelper.createProbeHttpPortDecorator(name, KUBERNETES, config.readinessProbe, ports));

// Handle remote debug configuration
if (config.remoteDebug.enabled) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<HasMetadata> 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);
});
});
});
});
});
});
}
}

0 comments on commit 664ce65

Please sign in to comment.