Skip to content

Commit

Permalink
Inherit Healthcheck from base image (#1288)
Browse files Browse the repository at this point in the history
  • Loading branch information
TadCordle authored Dec 3, 2018
1 parent f59326e commit 36c152a
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ private Image<Layer> afterCachedLayerSteps()
imageBuilder
.addEnvironment(baseImage.getEnvironment())
.addLabels(baseImage.getLabels())
.setHealthCheck(baseImage.getHealthCheck())
.addExposedPorts(baseImage.getExposedPorts())
.addVolumes(baseImage.getVolumes())
.setWorkingDirectory(baseImage.getWorkingDirectory());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
Expand All @@ -37,7 +36,6 @@ public static class Builder {
@Nullable private Integer retries;

private Builder(ImmutableList<String> command) {
Preconditions.checkArgument(command.size() > 1, "command must not be empty");
this.command = command;
}

Expand Down Expand Up @@ -92,58 +90,15 @@ public DockerHealthCheck build() {
}

/**
* Creates a disabled {@link DockerHealthCheck} (corresponds to "NONE" in container config).
* Creates a new {@link DockerHealthCheck.Builder} with the specified command.
*
* @return the new {@link DockerHealthCheck}
* @param command the command
* @return a new {@link DockerHealthCheck.Builder}
*/
public static DockerHealthCheck disabled() {
return new DockerHealthCheck(ImmutableList.of("NONE"), null, null, null, null);
}

/**
* Creates a new {@link DockerHealthCheck} with the command set to be inherited from the base
* image.
*
* @return the new {@link DockerHealthCheck}
*/
public static DockerHealthCheck inherited() {
return new DockerHealthCheck(ImmutableList.of(), null, null, null, null);
}

/**
* Creates a new {@link DockerHealthCheck.Builder} with the specified healthcheck command to be
* directly executed (corresponds to "CMD" in container config).
*
* @param command the healthcheck command to execute
* @return the new {@link DockerHealthCheck.Builder}
*/
public static Builder builderWithExecCommand(List<String> command) {
return new Builder(ImmutableList.<String>builder().add("CMD").addAll(command).build());
}

/**
* Creates a new {@link DockerHealthCheck.Builder} with the specified healthcheck command to be
* directly executed (corresponds to "CMD" in container config).
*
* @param command the healthcheck command to execute
* @return the new {@link DockerHealthCheck.Builder}
*/
public static Builder builderWithExecCommand(String... command) {
return new Builder(
ImmutableList.<String>builder().add("CMD").addAll(Arrays.asList(command)).build());
}

/**
* Creates a new {@link DockerHealthCheck.Builder} with the specified healthcheck command to be
* run by the container's default shell (corresponds to "CMD-SHELL" in container config). This
* command cannot be run on containers with no default shell.
*
* @param command the shell command to run
* @return the new {@link DockerHealthCheck.Builder}
*/
public static Builder builderWithShellCommand(String command) {
Preconditions.checkArgument(!command.trim().isEmpty(), "command must not be empty/whitespace");
return new Builder(ImmutableList.of("CMD-SHELL", command));
public static DockerHealthCheck.Builder fromCommand(List<String> command) {
Preconditions.checkArgument(command.size() > 0, "command must not be empty");
Preconditions.checkArgument(!command.contains(null), "command must not contain null elements");
return new Builder(ImmutableList.copyOf(command));
}

private final ImmutableList<String> command;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static class Builder<T extends Layer> {
@Nullable private Instant created;
@Nullable private ImmutableList<String> entrypoint;
@Nullable private ImmutableList<String> programArguments;
private DockerHealthCheck healthCheck = DockerHealthCheck.inherited();
@Nullable private DockerHealthCheck healthCheck;
@Nullable private String workingDirectory;
@Nullable private String user;

Expand Down Expand Up @@ -136,7 +136,7 @@ public Builder<T> setProgramArguments(@Nullable List<String> programArguments) {
* @param healthCheck the healthcheck configuration
* @return this
*/
public Builder<T> setHealthCheck(DockerHealthCheck healthCheck) {
public Builder<T> setHealthCheck(@Nullable DockerHealthCheck healthCheck) {
this.healthCheck = healthCheck;
return this;
}
Expand Down Expand Up @@ -271,7 +271,7 @@ public static <T extends Layer> Builder<T> builder(
@Nullable private final ImmutableList<String> programArguments;

/** Healthcheck configuration. */
private final DockerHealthCheck healthCheck;
@Nullable private final DockerHealthCheck healthCheck;

/** Ports that the container listens on. */
@Nullable private final ImmutableSet<Port> exposedPorts;
Expand All @@ -296,7 +296,7 @@ private Image(
@Nullable ImmutableMap<String, String> environment,
@Nullable ImmutableList<String> entrypoint,
@Nullable ImmutableList<String> programArguments,
DockerHealthCheck healthCheck,
@Nullable DockerHealthCheck healthCheck,
@Nullable ImmutableSet<Port> exposedPorts,
@Nullable ImmutableSet<AbsoluteUnixPath> volumes,
@Nullable ImmutableMap<String, String> labels,
Expand Down Expand Up @@ -341,6 +341,7 @@ public ImmutableList<String> getProgramArguments() {
return programArguments;
}

@Nullable
public DockerHealthCheck getHealthCheck() {
return healthCheck;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ public Blob getContainerConfigurationBlob() {

// Ignore healthcheck if not Docker/command is empty
DockerHealthCheck healthCheck = image.getHealthCheck();
if (image.getImageFormat() == V22ManifestTemplate.class
&& !healthCheck.getCommand().isEmpty()) {
if (image.getImageFormat() == V22ManifestTemplate.class && healthCheck != null) {
template.setContainerHealthCheckTest(healthCheck.getCommand());
healthCheck
.getInterval()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.cloud.tools.jib.image.json;

import com.google.cloud.tools.jib.blob.BlobDescriptor;
import com.google.cloud.tools.jib.configuration.DockerHealthCheck;
import com.google.cloud.tools.jib.configuration.Port;
import com.google.cloud.tools.jib.filesystem.AbsoluteUnixPath;
import com.google.cloud.tools.jib.image.DescriptorDigest;
Expand All @@ -29,6 +30,7 @@
import com.google.cloud.tools.jib.image.ReferenceNoDiffIdLayer;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
Expand Down Expand Up @@ -146,6 +148,27 @@ public static Image<Layer> toImage(
imageBuilder.setProgramArguments(containerConfigurationTemplate.getContainerCmd());
}

List<String> baseHealthCheckCommand = containerConfigurationTemplate.getContainerHealthTest();
if (baseHealthCheckCommand != null) {
DockerHealthCheck.Builder builder = DockerHealthCheck.fromCommand(baseHealthCheckCommand);
if (containerConfigurationTemplate.getContainerHealthInterval() != null) {
builder.setInterval(
Duration.ofNanos(containerConfigurationTemplate.getContainerHealthInterval()));
}
if (containerConfigurationTemplate.getContainerHealthTimeout() != null) {
builder.setTimeout(
Duration.ofNanos(containerConfigurationTemplate.getContainerHealthTimeout()));
}
if (containerConfigurationTemplate.getContainerHealthStartPeriod() != null) {
builder.setStartPeriod(
Duration.ofNanos(containerConfigurationTemplate.getContainerHealthStartPeriod()));
}
if (containerConfigurationTemplate.getContainerHealthRetries() != null) {
builder.setRetries(containerConfigurationTemplate.getContainerHealthRetries());
}
imageBuilder.setHealthCheck(builder.build());
}

if (containerConfigurationTemplate.getContainerExposedPorts() != null) {
imageBuilder.addExposedPorts(
portMapToSet(containerConfigurationTemplate.getContainerExposedPorts()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.cloud.tools.jib.cache.CachedLayer;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.configuration.ContainerConfiguration;
import com.google.cloud.tools.jib.configuration.DockerHealthCheck;
import com.google.cloud.tools.jib.configuration.Port;
import com.google.cloud.tools.jib.event.EventDispatcher;
import com.google.cloud.tools.jib.filesystem.AbsoluteUnixPath;
Expand All @@ -36,6 +37,7 @@
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import java.security.DigestException;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
Expand Down Expand Up @@ -133,6 +135,13 @@ public BlobDescriptor getBlobDescriptor() {
.setWorkingDirectory("/base/working/directory")
.setEntrypoint(ImmutableList.of("baseImageEntrypoint"))
.setProgramArguments(ImmutableList.of("catalina.sh", "run"))
.setHealthCheck(
DockerHealthCheck.fromCommand(ImmutableList.of("CMD-SHELL", "echo hi"))
.setInterval(Duration.ofSeconds(3))
.setTimeout(Duration.ofSeconds(2))
.setStartPeriod(Duration.ofSeconds(1))
.setRetries(20)
.build())
.addExposedPorts(ImmutableSet.of(Port.tcp(1000), Port.udp(2000)))
.addVolumes(
ImmutableSet.of(
Expand Down Expand Up @@ -228,6 +237,17 @@ public void test_propagateBaseImageConfiguration()
"base.label.2",
"new.value"),
image.getLabels());
Assert.assertNotNull(image.getHealthCheck());
Assert.assertEquals(
ImmutableList.of("CMD-SHELL", "echo hi"), image.getHealthCheck().getCommand());
Assert.assertTrue(image.getHealthCheck().getInterval().isPresent());
Assert.assertEquals(Duration.ofSeconds(3), image.getHealthCheck().getInterval().get());
Assert.assertTrue(image.getHealthCheck().getTimeout().isPresent());
Assert.assertEquals(Duration.ofSeconds(2), image.getHealthCheck().getTimeout().get());
Assert.assertTrue(image.getHealthCheck().getStartPeriod().isPresent());
Assert.assertEquals(Duration.ofSeconds(1), image.getHealthCheck().getStartPeriod().get());
Assert.assertTrue(image.getHealthCheck().getRetries().isPresent());
Assert.assertEquals(20, (int) image.getHealthCheck().getRetries().get());
Assert.assertEquals(
ImmutableSet.of(Port.tcp(1000), Port.udp(2000), Port.tcp(3000), Port.udp(4000)),
image.getExposedPorts());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@

import com.google.common.collect.ImmutableList;
import java.time.Duration;
import java.util.Arrays;
import org.junit.Assert;
import org.junit.Test;

/** Tests for {@link DockerHealthCheck}. */
public class DockerHealthCheckTest {

@Test
public void testBuild_parameters() {
public void testBuild() {
DockerHealthCheck healthCheck =
DockerHealthCheck.builderWithShellCommand("echo hi")
DockerHealthCheck.fromCommand(ImmutableList.of("echo", "hi"))
.setInterval(Duration.ofNanos(123))
.setTimeout(Duration.ofNanos(456))
.setStartPeriod(Duration.ofNanos(789))
Expand All @@ -45,35 +46,19 @@ public void testBuild_parameters() {
}

@Test
public void testBuild_propagated() {
DockerHealthCheck healthCheck = DockerHealthCheck.inherited();
Assert.assertTrue(healthCheck.getCommand().isEmpty());
}

@Test
public void testBuild_execArray() {
DockerHealthCheck healthCheck =
DockerHealthCheck.builderWithExecCommand("test", "command").build();
Assert.assertEquals(ImmutableList.of("CMD", "test", "command"), healthCheck.getCommand());
}

@Test
public void testBuild_execList() {
DockerHealthCheck healthCheck =
DockerHealthCheck.builderWithExecCommand(ImmutableList.of("test", "command")).build();
Assert.assertEquals(ImmutableList.of("CMD", "test", "command"), healthCheck.getCommand());
}
public void testBuild_invalidCommand() {
try {
DockerHealthCheck.fromCommand(ImmutableList.of());
Assert.fail();
} catch (IllegalArgumentException ex) {
Assert.assertEquals("command must not be empty", ex.getMessage());
}

@Test
public void testBuild_shell() {
DockerHealthCheck healthCheck =
DockerHealthCheck.builderWithShellCommand("shell command").build();
Assert.assertEquals(ImmutableList.of("CMD-SHELL", "shell command"), healthCheck.getCommand());
}

@Test
public void testDisabled() {
DockerHealthCheck healthCheck = DockerHealthCheck.disabled();
Assert.assertEquals(ImmutableList.of("NONE"), healthCheck.getCommand());
try {
DockerHealthCheck.fromCommand(Arrays.asList("CMD", null));
Assert.fail();
} catch (IllegalArgumentException ex) {
Assert.assertEquals("command must not contain null elements", ex.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private void setUp(Class<? extends BuildableManifestTemplate> imageFormat)
.setEntrypoint(Arrays.asList("some", "entrypoint", "command"))
.setProgramArguments(Arrays.asList("arg1", "arg2"))
.setHealthCheck(
DockerHealthCheck.builderWithShellCommand("/checkhealth")
DockerHealthCheck.fromCommand(ImmutableList.of("CMD-SHELL", "/checkhealth"))
.setInterval(Duration.ofSeconds(3))
.setTimeout(Duration.ofSeconds(1))
.setStartPeriod(Duration.ofSeconds(2))
Expand Down
1 change: 1 addition & 0 deletions jib-gradle-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- `container.workingDirectory` configuration parameter to set the working directory ([#1225](https:/GoogleContainerTools/jib/issues/1225))
- Adds support for configuring volumes ([#1121](https:/GoogleContainerTools/jib/issues/1121))
- Exposed ports are now propagated from the base image ([#595](https:/GoogleContainerTools/jib/issues/595))
- Docker health check is now propagated from the base image ([#595](https:/GoogleContainerTools/jib/issues/595))

### Changed

Expand Down
1 change: 1 addition & 0 deletions jib-maven-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- `<container><workingDirectory>` configuration parameter to set the working directory ([#1225](https:/GoogleContainerTools/jib/issues/1225))
- Adds support for configuring volumes ([#1121](https:/GoogleContainerTools/jib/issues/1121))
- Exposed ports are now propagated from the base image ([#595](https:/GoogleContainerTools/jib/issues/595))
- Docker health check is now propagated from the base image ([#595](https:/GoogleContainerTools/jib/issues/595))

### Changed

Expand Down

0 comments on commit 36c152a

Please sign in to comment.