diff --git a/samples/healthcheck/pom.xml b/samples/healthcheck/pom.xml index 08e944dfe..85abe6f14 100644 --- a/samples/healthcheck/pom.xml +++ b/samples/healthcheck/pom.xml @@ -102,7 +102,21 @@ - unhealthybox5 + healthybox5 + busybox5 + + busybox + + 5m + 3s + 30m + 3 + curl -f http://localhost/ || exit 1 + + + + + unhealthybox6 busybox5 busybox diff --git a/src/main/asciidoc/inc/build/_healthcheck.adoc b/src/main/asciidoc/inc/build/_healthcheck.adoc index b205c9165..bd2cadb68 100644 --- a/src/main/asciidoc/inc/build/_healthcheck.adoc +++ b/src/main/asciidoc/inc/build/_healthcheck.adoc @@ -21,6 +21,9 @@ The healtcheck configuration can have the following options | *retries* | How many retries should be performed before the container is to be considered unhealthy. +| *startPeriod* +| Initialization time for containers that need time to bootstrap. Probe failure during that period will not be counted towards the maximum number of retries. However, if a health check succeeds during the start period, the container is considered started and all consecutive failures will be counted towards the maximum number of retries. Given in seconds, but another time unit can be appended. + | *timeout* | Timeout after which healthckeck should be stopped and considered to have failed. Given in seconds, but another time unit can be appended. |=== @@ -35,6 +38,8 @@ The following example queries an URL every 10s as an healthcheck: 5m 3s + + 30m 3 diff --git a/src/main/asciidoc/inc/external/_property_configuration.adoc b/src/main/asciidoc/inc/external/_property_configuration.adoc index 7d9c55552..5773ce9eb 100644 --- a/src/main/asciidoc/inc/external/_property_configuration.adoc +++ b/src/main/asciidoc/inc/external/_property_configuration.adoc @@ -145,6 +145,9 @@ when a `docker.from` or a `docker.fromExt` is set. | *docker.healthcheck.retries* | Number of retries for how often to retry a healthcheck until it is considered to have failed +| *docker.healthcheck.startPeriod* +| Initialization time for containers that need time to bootstrap. Probe failure during that period will not be counted towards the maximum number of retries. However, if a health check succeeds during the start period, the container is considered started and all consecutive failures will be counted towards the maximum number of retries. (in seconds or with a given time unit) + | *docker.healthcheck.timeout* | Timeout after which a healthcheck command is considered to be failed (in seconds or with a given time unit) diff --git a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileBuilder.java b/src/main/java/io/fabric8/maven/docker/assembly/DockerFileBuilder.java index 27400c1f5..c14243923 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileBuilder.java +++ b/src/main/java/io/fabric8/maven/docker/assembly/DockerFileBuilder.java @@ -133,6 +133,7 @@ private void addHealthCheck(StringBuilder b) { case cmd: buildOption(healthString, DockerFileOption.HEALTHCHECK_INTERVAL, healthCheck.getInterval()); buildOption(healthString, DockerFileOption.HEALTHCHECK_TIMEOUT, healthCheck.getTimeout()); + buildOption(healthString, DockerFileOption.HEALTHCHECK_START_PERIOD, healthCheck.getStartPeriod()); buildOption(healthString, DockerFileOption.HEALTHCHECK_RETRIES, healthCheck.getRetries()); buildArguments(healthString, DockerFileKeyword.CMD, false, healthCheck.getCmd()); break; diff --git a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileOption.java b/src/main/java/io/fabric8/maven/docker/assembly/DockerFileOption.java index 1699ab312..a1a6806f6 100644 --- a/src/main/java/io/fabric8/maven/docker/assembly/DockerFileOption.java +++ b/src/main/java/io/fabric8/maven/docker/assembly/DockerFileOption.java @@ -7,6 +7,7 @@ public enum DockerFileOption { HEALTHCHECK_INTERVAL("interval"), HEALTHCHECK_TIMEOUT("timeout"), + HEALTHCHECK_START_PERIOD("start-period"), HEALTHCHECK_RETRIES("retries"); private String key; diff --git a/src/main/java/io/fabric8/maven/docker/config/HealthCheckConfiguration.java b/src/main/java/io/fabric8/maven/docker/config/HealthCheckConfiguration.java index cfe260622..1b7c62b20 100644 --- a/src/main/java/io/fabric8/maven/docker/config/HealthCheckConfiguration.java +++ b/src/main/java/io/fabric8/maven/docker/config/HealthCheckConfiguration.java @@ -13,6 +13,8 @@ public class HealthCheckConfiguration implements Serializable { private String timeout; + private String startPeriod; + private Integer retries; private Arguments cmd; @@ -27,6 +29,10 @@ public String getTimeout() { return prepareTimeValue(timeout); } + public String getStartPeriod() { + return prepareTimeValue(startPeriod); + } + private String prepareTimeValue(String timeout) { // Seconds as default if (timeout == null) { @@ -54,7 +60,7 @@ public void validate() throws IllegalArgumentException { switch(mode) { case none: - if (interval != null || timeout != null || retries != null || cmd != null) { + if (interval != null || timeout != null || startPeriod != null || retries != null || cmd != null) { throw new IllegalArgumentException("HealthCheck: no parameters are allowed when the health check mode is set to 'none'"); } break; @@ -85,6 +91,11 @@ public Builder timeout(String timeout) { return this; } + public Builder startPeriod(String startPeriod) { + config.startPeriod = startPeriod; + return this; + } + public Builder cmd(String command) { if (command != null) { config.cmd = new Arguments(command); diff --git a/src/main/java/io/fabric8/maven/docker/config/handler/property/ConfigKey.java b/src/main/java/io/fabric8/maven/docker/config/handler/property/ConfigKey.java index 84d6266b2..90f033ec8 100644 --- a/src/main/java/io/fabric8/maven/docker/config/handler/property/ConfigKey.java +++ b/src/main/java/io/fabric8/maven/docker/config/handler/property/ConfigKey.java @@ -64,6 +64,7 @@ public enum ConfigKey { HEALTHCHECK_MODE("healthcheck.mode"), HEALTHCHECK_INTERVAL("healthcheck.interval"), HEALTHCHECK_TIMEOUT("healthcheck.timeout"), + HEALTHCHECK_START_PERIOD("healthcheck.startPeriod"), HEALTHCHECK_RETRIES("healthcheck.retries"), HEALTHCHECK_CMD("healthcheck.cmd"), HOSTNAME, diff --git a/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java b/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java index 56a5d44cc..7c75a72f1 100644 --- a/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java +++ b/src/main/java/io/fabric8/maven/docker/config/handler/property/PropertyConfigHandler.java @@ -195,6 +195,7 @@ private HealthCheckConfiguration extractHealthCheck(HealthCheckConfiguration con return new HealthCheckConfiguration.Builder() .interval(valueProvider.getString(HEALTHCHECK_INTERVAL, config == null ? null : config.getInterval())) .timeout(valueProvider.getString(HEALTHCHECK_TIMEOUT, config == null ? null : config.getTimeout())) + .startPeriod(valueProvider.getString(HEALTHCHECK_START_PERIOD, config == null ? null : config.getStartPeriod())) .retries(valueProvider.getInteger(HEALTHCHECK_RETRIES, config == null ? null : config.getRetries())) .mode(valueProvider.getString(HEALTHCHECK_MODE, config == null || config.getMode() == null ? null : config.getMode().name())) .cmd(extractArguments(valueProvider, HEALTHCHECK_CMD, config == null ? null : config.getCmd())) diff --git a/src/test/java/io/fabric8/maven/docker/assembly/DockerFileBuilderTest.java b/src/test/java/io/fabric8/maven/docker/assembly/DockerFileBuilderTest.java index 96716cd6e..f99058549 100644 --- a/src/test/java/io/fabric8/maven/docker/assembly/DockerFileBuilderTest.java +++ b/src/test/java/io/fabric8/maven/docker/assembly/DockerFileBuilderTest.java @@ -182,9 +182,9 @@ public void testEntryPointParams() { @Test public void testHealthCheckCmdParams() { - HealthCheckConfiguration hc = new HealthCheckConfiguration.Builder().cmd("echo hello").interval("5s").timeout("3s").retries(4).build(); + HealthCheckConfiguration hc = new HealthCheckConfiguration.Builder().cmd("echo hello").interval("5s").timeout("3s").startPeriod("30s").retries(4).build(); String dockerfileContent = new DockerFileBuilder().healthCheck(hc).content(); - assertThat(dockerfileToMap(dockerfileContent), hasEntry("HEALTHCHECK", "--interval=5s --timeout=3s --retries=4 CMD echo hello")); + assertThat(dockerfileToMap(dockerfileContent), hasEntry("HEALTHCHECK", "--interval=5s --timeout=3s --start-period=30s --retries=4 CMD echo hello")); } @Test diff --git a/src/test/java/io/fabric8/maven/docker/config/HealthCheckConfigTest.java b/src/test/java/io/fabric8/maven/docker/config/HealthCheckConfigTest.java index 662c411d9..84a3f977c 100644 --- a/src/test/java/io/fabric8/maven/docker/config/HealthCheckConfigTest.java +++ b/src/test/java/io/fabric8/maven/docker/config/HealthCheckConfigTest.java @@ -48,17 +48,30 @@ public void testGoodHealthCheck4() { @Test public void testGoodHealthCheck5() { new HealthCheckConfiguration.Builder() - .mode(HealthCheckMode.cmd) .cmd("exit 0") .retries(1) .interval("2s") .timeout("3s") + .startPeriod("30s") .build() .validate(); } @Test public void testGoodHealthCheck6() { + new HealthCheckConfiguration.Builder() + .mode(HealthCheckMode.cmd) + .cmd("exit 0") + .retries(1) + .interval("2s") + .timeout("3s") + .startPeriod("4s") + .build() + .validate(); + } + + @Test + public void testGoodHealthCheck7() { new HealthCheckConfiguration.Builder() .mode(HealthCheckMode.none) .build() @@ -96,7 +109,7 @@ public void testBadHealthCheck3() { public void testBadHealthCheck4() { new HealthCheckConfiguration.Builder() .mode(HealthCheckMode.none) - .cmd("echo a") + .startPeriod("30s") .build() .validate(); } @@ -104,12 +117,21 @@ public void testBadHealthCheck4() { @Test(expected = IllegalArgumentException.class) public void testBadHealthCheck5() { new HealthCheckConfiguration.Builder() + .mode(HealthCheckMode.none) + .cmd("echo a") .build() .validate(); } @Test(expected = IllegalArgumentException.class) public void testBadHealthCheck6() { + new HealthCheckConfiguration.Builder() + .build() + .validate(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBadHealthCheck7() { new HealthCheckConfiguration.Builder() .mode(HealthCheckMode.cmd) .build()