Skip to content

Commit

Permalink
feat (jkube-kit/wildfly-jar): Add startup probe in WildFlyJARHealthCh…
Browse files Browse the repository at this point in the history
…eckEnricher (eclipse-jkube#1474)

Signed-off-by: Anurag Singh Rajawat <anuragsinghrajawat22@gmail.com>
  • Loading branch information
anurag-rajawat committed May 17, 2022
1 parent c6cca9e commit afea257
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Usage:
* Fix #1362: VolumePermissionEnricher : Replace iteration with bulk Collection.addAll call
* Fix #1382: Docker Build ARGS not replaced properly
* Fix #1324: Support legacy javaee as well as jakartaee projects in the Tomcat webapp generator
* Fix #1474: Add startup probe in WildflyJARHealthCheck enricher

### 1.7.0 (2022-02-25)
* Fix #1315: Pod Log Service works for Jobs with no selector
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
[[jkube-healthcheck-wildfly-jar]]
==== jkube-healthcheck-wildfly-jar

This enricher adds kubernetes readiness and liveness probes to WildFly JAR applications. Probes depend on the WildFly _microprofile-health_ subsystem
_/health/ready_ and _/health/live_ endpoints.
When the WildFly Bootable JAR Maven plugin is configured with the _<cloud>_ configuration item, _microprofile_health_ subsystem
This enricher adds kubernetes readiness, liveness and startup probes to WildFly JAR applications. Probes depend on the WildFly _microprofile-health_ subsystem
_/health/ready_, _/health/live_ and _/health/started_ endpoints.
When the WildFly Bootable JAR Maven plugin is configured with the _<cloud>_ configuration item, _microprofile-health_ subsystem
is enforced in the bootable JAR server configuration.

This enricher looks for the _<cloud>_ configuration item presence in the bootable JAR Maven plugin in order to add health check probes.
Expand All @@ -16,13 +16,15 @@ The enricher will use the following settings by default:
- scheme = `HTTP`
- readinessPath = `/health/ready`
- livenessPath = `/health/live`
- startupPath = `/health/started`
- livenessInitialDelay = `60`
- readinessInitialDelay = `10`
- startupInitialDelay = `10`
- failureThreshold = `3`
- successThreshold = `1`
- enforceProbes = 'false'

Setting the `port` to 0 or to a negative number disables liveness and readiness probes.
Setting the `port` to 0 or to a negative number disables liveness, readiness and startup probes.

These values can be configured by the enricher in the `{plugin}` configuration as shown below:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ private enum Config implements Configs.Config {
SUCCESSTHRESHOLD("successThreshold","1"),
LIVENESSINITIALDELAY("livenessInitialDelay", "60"),
READINESSINITIALDELAY("readinessInitialDelay", "10"),
STARTUPINITIALDELAY("startupInitialDelay", "10"),
READINESSPATH("readinessPath", "/health/ready"),
LIVENESSPATH("livenessPath", "/health/live"),
STARTUPPATH("startupPath", "/health/started"),
ENFORCEPROBES("enforceProbes","false");

@Getter
Expand All @@ -67,12 +69,17 @@ private enum Config implements Configs.Config {

@Override
protected Probe getReadinessProbe() {
return discoverWildflyJARHealthCheck(true);
return discoverWildflyJARHealthCheck(true, false);
}

@Override
protected Probe getLivenessProbe() {
return discoverWildflyJARHealthCheck(false);
return discoverWildflyJARHealthCheck(false, false);
}

@Override
protected Probe getStartupProbe() {
return discoverWildflyJARHealthCheck(false,true);
}

@Override
Expand Down Expand Up @@ -100,32 +107,41 @@ public void visit(ContainerBuilder containerBuilder) {
super.create(platformMode, builder);
}

private Probe discoverWildflyJARHealthCheck(boolean isReadiness) {
private Probe discoverWildflyJARHealthCheck(boolean isReadiness, boolean isStartup) {

if (isAvailable()) {
Integer port = getPort();
int port = getPort();
if (port <= 0) {
return null;
}
int initialDelay = isReadiness ? getReadinessInitialDelay() : getLivenessInitialDelay();
// scheme must be in upper case in k8s
String scheme = getScheme().toUpperCase();
String path = isReadiness ? getReadinessPath() : getLivenessPath();

return new ProbeBuilder()
.withNewHttpGet().withNewPort(port).withPath(path).withScheme(scheme).endHttpGet()
return new ProbeBuilder().withNewHttpGet()
.withNewPort(port).withPath(getProbePath(isReadiness, isStartup)).withScheme(scheme)
.endHttpGet()
.withFailureThreshold(getFailureThreshold())
.withSuccessThreshold(getSuccessThreshold())
.withInitialDelaySeconds(initialDelay).build();
.withInitialDelaySeconds(getInitialDelaySeconds(isReadiness, isStartup))
.build();
}
return null;
}

private Integer getInitialDelaySeconds(boolean isReadiness, boolean isStartup) {
if (isStartup) return getStartupInitialDelay();
return isReadiness ? getReadinessInitialDelay() : getLivenessInitialDelay();
}

private String getProbePath(boolean isReadiness, boolean isStartup) {
if (isStartup) return getStartupPath();
return isReadiness ? getReadinessPath() : getLivenessPath();
}

private boolean isAvailable() {
if (isProbeEnforced()) {
return true;
}
JavaProject project = ((JKubeEnricherContext) getContext()).getProject();
JavaProject project = getContext().getProject();
Plugin plugin = JKubeProjectUtil.getPlugin(project, BOOTABLE_JAR_GROUP_ID, BOOTABLE_JAR_ARTIFACT_ID);
if (plugin == null) {
return false;
Expand Down Expand Up @@ -169,4 +185,12 @@ protected String getReadinessPath() {
protected int getReadinessInitialDelay() {
return Configs.asInt(getConfig(Config.READINESSINITIALDELAY));
}

protected String getStartupPath() {
return Configs.asString(getConfig(Config.STARTUPPATH));
}

protected int getStartupInitialDelay() {
return Configs.asInt(getConfig(Config.STARTUPINITIALDELAY));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@
import org.eclipse.jkube.kit.config.resource.PlatformMode;
import org.eclipse.jkube.kit.config.resource.ProcessorConfig;
import org.eclipse.jkube.kit.enricher.api.model.Configuration;
import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;

public class WildflyJARHealthCheckEnricherTest {

Expand Down Expand Up @@ -85,6 +85,8 @@ public void testDefaultConfiguration(@Mocked final JavaProject project) {
assertNull(probe);
probe = enricher.getReadinessProbe();
assertNull(probe);
probe = enricher.getStartupProbe();
assertNull(probe);
}

@Test
Expand All @@ -103,6 +105,11 @@ public void testCloudConfiguration(@Mocked final JavaProject project) {
assertEquals("/health/ready", probe.getHttpGet().getPath());
assertEquals("HTTP", probe.getHttpGet().getScheme());
assertNotNull(probe);
probe = enricher.getStartupProbe();
assertEquals(9990, probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("/health/started", probe.getHttpGet().getPath());
assertEquals("HTTP", probe.getHttpGet().getScheme());
assertNotNull(probe);
}

@Test
Expand All @@ -111,10 +118,12 @@ public void testWithCustomConfigurationComingFromConf(@Mocked final JavaProject
jarConfig.put("cloud", null);
final Map<String, Map<String, Object>> config = createFakeConfig("{\"readinessPath\":\"/foo/ready\","
+ "\"livenessPath\":\"/foo/live\","
+ "\"startupPath\":\"/foo/started\","
+ "\"port\":\"1234\","
+ "\"scheme\":\"https\","
+"\"livenessInitialDelay\":\"99\","
+"\"readinessInitialDelay\":\"77\","
+"\"startupInitialDelay\":\"57\","
+"\"failureThreshold\":\"17\","
+"\"successThreshold\":\"27\""
+ "}");
Expand All @@ -130,6 +139,7 @@ public void testWithCustomConfigurationComingFromConf(@Mocked final JavaProject
assertEquals(99, probe.getInitialDelaySeconds().intValue());
assertEquals(27, probe.getSuccessThreshold().intValue());
assertEquals(17, probe.getFailureThreshold().intValue());

probe = enricher.getReadinessProbe();
assertNotNull(probe);
assertEquals("HTTPS", probe.getHttpGet().getScheme());
Expand All @@ -139,6 +149,16 @@ public void testWithCustomConfigurationComingFromConf(@Mocked final JavaProject
assertEquals(77, probe.getInitialDelaySeconds().intValue());
assertEquals(27, probe.getSuccessThreshold().intValue());
assertEquals(17, probe.getFailureThreshold().intValue());

probe = enricher.getStartupProbe();
assertNotNull(probe);
assertEquals("HTTPS", probe.getHttpGet().getScheme());
assertNull(probe.getHttpGet().getHost());
assertEquals(1234, probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("/foo/started", probe.getHttpGet().getPath());
assertEquals(57, probe.getInitialDelaySeconds().intValue());
assertEquals(27, probe.getSuccessThreshold().intValue());
assertEquals(17, probe.getFailureThreshold().intValue());
}

@Test
Expand All @@ -155,6 +175,8 @@ public void testDisableHealth(@Mocked final JavaProject project) {
assertNull(probe);
probe = enricher.getReadinessProbe();
assertNull(probe);
probe = enricher.getStartupProbe();
assertNull(probe);
}

@Test
Expand All @@ -170,11 +192,18 @@ public void testEnforceTrueHealth() {
assertEquals(9990, probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("/health/live", probe.getHttpGet().getPath());
assertEquals("HTTP", probe.getHttpGet().getScheme());

probe = enricher.getReadinessProbe();
assertEquals(9990, probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("/health/ready", probe.getHttpGet().getPath());
assertEquals("HTTP", probe.getHttpGet().getScheme());
assertNotNull(probe);

probe = enricher.getStartupProbe();
assertNotNull(probe);
assertEquals(9990, probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("/health/started", probe.getHttpGet().getPath());
assertEquals("HTTP", probe.getHttpGet().getScheme());
}

@Test
Expand All @@ -189,15 +218,18 @@ public void testEnforceFalseHealth() {
assertNull(probe);
probe = enricher.getReadinessProbe();
assertNull(probe);
probe = enricher.getStartupProbe();
assertNull(probe);
}

@Test
public void configureWildFlyJarHealthPort() {
final WildflyJARHealthCheckEnricher enricher = new WildflyJARHealthCheckEnricher(context);
final int port = enricher.getPort();
Assert.assertEquals(9990, port);
Assert.assertEquals("/health/live", enricher.getLivenessPath());
Assert.assertEquals("/health/ready", enricher.getReadinessPath());
assertEquals(9990, port);
assertEquals("/health/live", enricher.getLivenessPath());
assertEquals("/health/ready", enricher.getReadinessPath());
assertEquals("/health/started", enricher.getStartupPath());
}

@Test
Expand All @@ -224,15 +256,15 @@ public void visit(ContainerBuilder containerBuilder) {
}
});

Assert.assertEquals(1, containerBuilders.size());
assertEquals(1, containerBuilders.size());
ContainerBuilder cb = containerBuilders.get(0);
List<EnvVar> env = cb.build().getEnv();
Assert.assertEquals(1, env.size());
assertEquals(1, env.size());
EnvVar hostName = env.get(0);
Assert.assertEquals("HOSTNAME", hostName.getName());
Assert.assertNotNull(hostName.getValueFrom());
assertEquals("HOSTNAME", hostName.getName());
assertNotNull(hostName.getValueFrom());
EnvVarSource src = hostName.getValueFrom();
Assert.assertEquals("metadata.name", src.getFieldRef().getFieldPath());
assertEquals("metadata.name", src.getFieldRef().getFieldPath());
}

private Map<String, Map<String, Object>> createFakeConfig(String config) {
Expand Down

0 comments on commit afea257

Please sign in to comment.