Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the default base images from Distroless in Jib build plugins #3124

Merged
merged 13 commits into from
Apr 5, 2021
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
* Exception when the Java version in the base image is incompatible with the Java version of the
* application to be containerized. For example, when the project is Java 11 but the base image is
* {@code gcr.io/distroless/java:8}.
* {@code adoptopenjdk:8-jre}.
*/
public class IncompatibleBaseImageJavaVersionException extends Exception {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ public static JibContainerBuilder fromExplodedWar(
javaContainerBuilder.addClasses(webInfClasses, isClassFile);
}
if (Files.exists(webInfLib)) {

javaContainerBuilder.addDependencies(
new DirectoryWalker(webInfLib)
.filterRoot()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
Expand Down Expand Up @@ -84,7 +85,7 @@ public class PluginConfigurationProcessor {
private static final ImmutableList<String> CONST_LAYERS =
ImmutableList.of(LayerType.DEPENDENCIES.getName());

private static final String DEFAULT_JETTY_APP_ROOT = "/jetty/webapps/ROOT";
private static final String DEFAULT_JETTY_APP_ROOT = "/var/lib/jetty/webapps/ROOT";

/**
* Generate a runner for image builds to docker daemon.
Expand Down Expand Up @@ -502,10 +503,10 @@ static JavaContainerBuilder getJavaContainerBuilderWithBaseImage(
// Verify Java version is compatible
String prefixRemoved = baseImageConfig.replaceFirst(".*://", "");
int javaVersion = projectProperties.getMajorJavaVersion();
if (isKnownDistrolessJava8Image(prefixRemoved) && javaVersion > 8) {
if (isKnownJava8Image(prefixRemoved) && javaVersion > 8) {
throw new IncompatibleBaseImageJavaVersionException(8, javaVersion);
}
if (isKnownDistrolessJava11Image(prefixRemoved) && javaVersion > 11) {
if (isKnownJava11Image(prefixRemoved) && javaVersion > 11) {
throw new IncompatibleBaseImageJavaVersionException(11, javaVersion);
}

Expand Down Expand Up @@ -542,7 +543,7 @@ static JavaContainerBuilder getJavaContainerBuilderWithBaseImage(
* <ol>
* <li>null (inheriting from the base image), if the user specified value is {@code INHERIT}
* <li>the user specified one, if set
* <li>for a WAR project, null (it must be inherited from base image)
* <li>for a WAR project, {@code ["java", "-jar", "/usr/local/jetty/start.jar"]}
* <li>for a non-WAR project, by resolving the main class
* </ol>
*
Expand Down Expand Up @@ -588,7 +589,7 @@ static List<String> computeEntrypoint(
"mainClass, extraClasspath, jvmFlags, and expandClasspathDependencies "
+ "are ignored for WAR projects"));
}
return null;
return Arrays.asList("java", "-jar", "/usr/local/jetty/start.jar");
chanseokoh marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FTR: it was wrong to return this when a custom base image is specified. The issue is fixed later in #3185.

}

List<String> classpath = new ArrayList<>(rawExtraClasspath);
Expand Down Expand Up @@ -634,8 +635,8 @@ static List<String> computeEntrypoint(

/**
* Gets the suitable value for the base image. If the raw base image parameter is null, returns
* {@code "gcr.io/distroless/java/jetty"} for WAR projects or {@code "gcr.io/distroless/java"} for
* non-WAR.
* {@code "jetty"} for WAR projects or {@code "adoptopenjdk:8-jre"} or {@code
* "adoptopenjdk:11-jre"} for non-WAR.
*
* @param projectProperties used for providing additional information
* @return the base image
Expand All @@ -645,16 +646,14 @@ static List<String> computeEntrypoint(
@VisibleForTesting
static String getDefaultBaseImage(ProjectProperties projectProperties)
throws IncompatibleBaseImageJavaVersionException {
if (projectProperties.isWarProject()) {
return "jetty";
}
int javaVersion = projectProperties.getMajorJavaVersion();
if (javaVersion <= 8) {
return projectProperties.isWarProject()
? "gcr.io/distroless/java/jetty:java8"
: "gcr.io/distroless/java:8";
}
if (javaVersion <= 11) {
return projectProperties.isWarProject()
? "gcr.io/distroless/java/jetty:java11"
: "gcr.io/distroless/java:11";
return "adoptopenjdk:8-jre";
} else if (javaVersion <= 11) {
return "adoptopenjdk:11-jre";
}
throw new IncompatibleBaseImageJavaVersionException(11, javaVersion);
}
Expand Down Expand Up @@ -721,8 +720,8 @@ static Set<AbsoluteUnixPath> getVolumesSet(RawConfiguration rawConfiguration)

/**
* Gets the value of the {@code appRoot} parameter. If the parameter is empty, returns {@code
* /jetty/webapps/ROOT} for WAR projects or {@link JavaContainerBuilder#DEFAULT_APP_ROOT} for
* other projects.
* /var/lib/jetty/webapps/ROOT} for WAR projects or {@link JavaContainerBuilder#DEFAULT_APP_ROOT}
* for other projects.
*
* @param rawConfiguration raw configuration data
* @param projectProperties the project properties
Expand Down Expand Up @@ -952,40 +951,22 @@ private static Path getCheckedCacheDirectory(String property, Path defaultPath)
}

/**
* Checks if the given image is a known Java 8 distroless image. Checking against only images
* known to Java 8, the method may to return {@code false} for Java 8 distroless unknown to it.
* Checks if the given image is a known Java 8 image. May return false negative.
*
* @param imageReference the image reference
* @return {@code true} if the image is equal to one of the known Java 8 distroless images, else
* {@code false}
* @return {@code true} if the image is a known Java 8 image
*/
private static boolean isKnownDistrolessJava8Image(String imageReference) {
// TODO: drop "latest", "debug", and the like once they no longer point to Java 8.
return imageReference.equals("gcr.io/distroless/java")
|| imageReference.equals("gcr.io/distroless/java:latest")
|| imageReference.equals("gcr.io/distroless/java:debug")
|| imageReference.equals("gcr.io/distroless/java:8")
|| imageReference.equals("gcr.io/distroless/java:8-debug")
|| imageReference.equals("gcr.io/distroless/java/jetty")
|| imageReference.equals("gcr.io/distroless/java/jetty:latest")
|| imageReference.equals("gcr.io/distroless/java/jetty:debug")
|| imageReference.equals("gcr.io/distroless/java/jetty:java8")
|| imageReference.equals("gcr.io/distroless/java/jetty:java8-debug");
private static boolean isKnownJava8Image(String imageReference) {
return imageReference.startsWith("adoptopenjdk:8");
}

/**
* Checks if the given image is a known Java 11 distroless image. Checking against only images
* known to Java 11, the method may to return {@code false} for Java 11 distroless unknown to it.
* Checks if the given image is a known Java 11 image. May return false negative.
*
* @param imageReference the image reference
* @return {@code true} if the image is equal to one of the known Java 11 distroless images, else
* {@code false}
* @return {@code true} if the image is a known Java 11 image
*/
private static boolean isKnownDistrolessJava11Image(String imageReference) {
// TODO: add "latest", "debug", and the like to this list once they point to Java 11.
return imageReference.equals("gcr.io/distroless/java:11")
|| imageReference.equals("gcr.io/distroless/java:11-debug")
|| imageReference.equals("gcr.io/distroless/java/jetty:java11")
|| imageReference.equals("gcr.io/distroless/java/jetty:java11-debug");
private static boolean isKnownJava11Image(String imageReference) {
return imageReference.startsWith("adoptopenjdk:11");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,9 @@ public void testEntrypoint_defaultWarPackaging()

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
assertThat(buildContext.getContainerConfiguration().getEntrypoint())
.containsExactly("java", "-jar", "/usr/local/jetty/start.jar")
.inOrder();
verifyNoInteractions(logger);
}

Expand Down Expand Up @@ -516,7 +518,9 @@ public void testEntrypoint_warningOnMainclassForWar()

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
assertThat(buildContext.getContainerConfiguration().getEntrypoint())
.containsExactly("java", "-jar", "/usr/local/jetty/start.jar")
.inOrder();
verify(projectProperties)
.log(
LogEvent.warn(
Expand All @@ -536,7 +540,9 @@ public void testEntrypoint_warningOnExpandClasspathDependenciesForWar()

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
assertThat(buildContext.getContainerConfiguration().getEntrypoint())
.containsExactly("java", "-jar", "/usr/local/jetty/start.jar")
.inOrder();
verify(projectProperties)
.log(
LogEvent.warn(
Expand All @@ -562,21 +568,6 @@ public void testEntrypointClasspath_nonDefaultAppRoot()
.inOrder();
}

@Test
public void testWebAppEntrypoint_inheritedFromBaseImage()
throws InvalidImageReferenceException, IOException, CacheDirectoryCreationException,
MainClassInferenceException, InvalidAppRootException, InvalidWorkingDirectoryException,
InvalidPlatformException, InvalidContainerVolumeException,
IncompatibleBaseImageJavaVersionException, NumberFormatException,
InvalidContainerizingModeException, InvalidFilesModificationTimeException,
InvalidCreationTimeException {
when(projectProperties.isWarProject()).thenReturn(true);

BuildContext buildContext = getBuildContext(processCommonConfiguration());

assertThat(buildContext.getContainerConfiguration().getEntrypoint()).isNull();
}

@Test
public void testGetAppRootChecked() throws InvalidAppRootException {
when(rawConfiguration.getAppRoot()).thenReturn("/some/root");
Expand Down Expand Up @@ -639,7 +630,7 @@ public void testGetAppRootChecked_defaultWarProject() throws InvalidAppRootExcep
when(projectProperties.isWarProject()).thenReturn(true);

assertThat(PluginConfigurationProcessor.getAppRootChecked(rawConfiguration, projectProperties))
.isEqualTo(AbsoluteUnixPath.get("/jetty/webapps/ROOT"));
.isEqualTo(AbsoluteUnixPath.get("/var/lib/jetty/webapps/ROOT"));
}

@Test
Expand Down Expand Up @@ -691,7 +682,7 @@ public void testGetDefaultBaseImage_nonWarPackaging()
when(projectProperties.isWarProject()).thenReturn(false);

assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");
.isEqualTo("adoptopenjdk:8-jre");
}

@Test
Expand All @@ -700,73 +691,39 @@ public void testGetDefaultBaseImage_warProject()
when(projectProperties.isWarProject()).thenReturn(true);

assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
}

@Test
public void testGetDefaultBaseImage_chooseJava8Distroless()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(6);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");

when(projectProperties.getMajorJavaVersion()).thenReturn(7);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");

when(projectProperties.getMajorJavaVersion()).thenReturn(8);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:8");
}

@Test
public void testGetDefaultBaseImage_chooseJava11Distroless()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(9);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:11");

when(projectProperties.getMajorJavaVersion()).thenReturn(10);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:11");

when(projectProperties.getMajorJavaVersion()).thenReturn(11);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java:11");
.isEqualTo("jetty");
}

@Test
public void testGetDefaultBaseImage_chooseJava8JettyDistroless()
public void testGetDefaultBaseImage_chooseJava8BaseImage()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(6);
when(projectProperties.isWarProject()).thenReturn(true);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
.isEqualTo("adoptopenjdk:8-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(7);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
.isEqualTo("adoptopenjdk:8-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(8);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java8");
.isEqualTo("adoptopenjdk:8-jre");
}

@Test
public void testGetDefaultBaseImage_chooseJava11JettyDistroless()
public void testGetDefaultBaseImage_chooseJava11BaseImage()
throws IncompatibleBaseImageJavaVersionException {
when(projectProperties.getMajorJavaVersion()).thenReturn(9);
when(projectProperties.isWarProject()).thenReturn(true);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java11");
.isEqualTo("adoptopenjdk:11-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(10);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java11");
.isEqualTo("adoptopenjdk:11-jre");

when(projectProperties.getMajorJavaVersion()).thenReturn(11);
assertThat(PluginConfigurationProcessor.getDefaultBaseImage(projectProperties))
.isEqualTo("gcr.io/distroless/java/jetty:java11");
.isEqualTo("adoptopenjdk:11-jre");
}

@Test
Expand Down Expand Up @@ -829,7 +786,7 @@ public void testGetJavaContainerBuilderWithBaseImage_registryWithPrefix()
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8BaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(11);

when(rawConfiguration.getFromImage()).thenReturn(Optional.of("gcr.io/distroless/java:8"));
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:8"));
IncompatibleBaseImageJavaVersionException exception1 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
Expand All @@ -839,7 +796,7 @@ public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8BaseImage(
assertThat(exception1.getBaseImageMajorJavaVersion()).isEqualTo(8);
assertThat(exception1.getProjectMajorJavaVersion()).isEqualTo(11);

when(rawConfiguration.getFromImage()).thenReturn(Optional.of("gcr.io/distroless/java:latest"));
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:8-jre"));
IncompatibleBaseImageJavaVersionException exception2 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
Expand All @@ -854,47 +811,25 @@ public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8BaseImage(
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava11BaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(15);

when(rawConfiguration.getFromImage()).thenReturn(Optional.of("gcr.io/distroless/java:11"));
IncompatibleBaseImageJavaVersionException exception =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
() ->
PluginConfigurationProcessor.getJavaContainerBuilderWithBaseImage(
rawConfiguration, projectProperties, inferredAuthProvider));
assertThat(exception.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception.getProjectMajorJavaVersion()).isEqualTo(15);
}

@Test
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava8JettyBaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(11);

when(rawConfiguration.getFromImage())
.thenReturn(Optional.of("gcr.io/distroless/java/jetty:java8"));
IncompatibleBaseImageJavaVersionException exception =
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:11"));
IncompatibleBaseImageJavaVersionException exception1 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
() ->
PluginConfigurationProcessor.getJavaContainerBuilderWithBaseImage(
rawConfiguration, projectProperties, inferredAuthProvider));
assertThat(exception.getBaseImageMajorJavaVersion()).isEqualTo(8);
assertThat(exception.getProjectMajorJavaVersion()).isEqualTo(11);
}

@Test
public void testGetJavaContainerBuilderWithBaseImage_incompatibleJava11JettyBaseImage() {
when(projectProperties.getMajorJavaVersion()).thenReturn(15);
assertThat(exception1.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception1.getProjectMajorJavaVersion()).isEqualTo(15);

when(rawConfiguration.getFromImage())
.thenReturn(Optional.of("gcr.io/distroless/java/jetty:java11"));
IncompatibleBaseImageJavaVersionException exception =
when(rawConfiguration.getFromImage()).thenReturn(Optional.of("adoptopenjdk:11-jre"));
IncompatibleBaseImageJavaVersionException exception2 =
assertThrows(
IncompatibleBaseImageJavaVersionException.class,
() ->
PluginConfigurationProcessor.getJavaContainerBuilderWithBaseImage(
rawConfiguration, projectProperties, inferredAuthProvider));
assertThat(exception.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception.getProjectMajorJavaVersion()).isEqualTo(15);
assertThat(exception2.getBaseImageMajorJavaVersion()).isEqualTo(11);
assertThat(exception2.getProjectMajorJavaVersion()).isEqualTo(15);
}

// https://github.com/GoogleContainerTools/jib/issues/1995
Expand Down