Skip to content

Commit

Permalink
When using buildx, do not force build of native platform
Browse files Browse the repository at this point in the history
closes #1572
  • Loading branch information
chonton authored and rohanKanojia committed Jul 1, 2022
1 parent d3cec33 commit d5cc609
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 31 deletions.
11 changes: 9 additions & 2 deletions src/main/java/io/fabric8/maven/docker/service/BuildXService.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,15 @@ private void removeConfigJson(Path configJson) {
}

private void buildMultiPlatform(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, File buildArchive) throws MojoExecutionException {
buildX(buildX, builderName, buildDirs, imageConfig, imageConfig.getBuildConfiguration().getBuildX().getPlatforms(), buildArchive, null);
buildX(buildX, builderName, buildDirs, imageConfig, Collections.singletonList(dockerAccess.getNativePlatform()), buildArchive, "--load");
// build the image
List<String> platforms = imageConfig.getBuildConfiguration().getBuildX().getPlatforms();
buildX(buildX, builderName, buildDirs, imageConfig, platforms, buildArchive, null);

// now load the native image by re-building, image should be cached and build should be quick
String nativePlatform = dockerAccess.getNativePlatform();
if (platforms.contains(nativePlatform)) {
buildX(buildX, builderName, buildDirs, imageConfig, Collections.singletonList(nativePlatform), buildArchive, "--load");
}
}

private void pushMultiPlatform(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, File buildArchive) throws MojoExecutionException {
Expand Down
71 changes: 58 additions & 13 deletions src/test/java/io/fabric8/maven/docker/BuildMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.fabric8.maven.docker.access.DockerAccessException;
import io.fabric8.maven.docker.assembly.DockerAssemblyManager;
import io.fabric8.maven.docker.config.BuildXConfiguration;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.service.BuildService;
import io.fabric8.maven.docker.service.BuildXService;
Expand All @@ -18,12 +19,15 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;

@ExtendWith(MockitoExtension.class)
class BuildMojoTest extends MojoTestBase {
private static final String NON_NATIVE_PLATFORM = "linux/amd64";
private static final String NATIVE_PLATFORM = "linux/arm64";
private static final String[] TWO_BUILDX_PLATFORMS = { NATIVE_PLATFORM, NON_NATIVE_PLATFORM };

@InjectMocks
private BuildMojo buildMojo;

Expand Down Expand Up @@ -74,7 +78,7 @@ void buildUsingBuildx() throws IOException, MojoExecutionException {

whenMojoExecutes();

thenBuildxRun(null, null);
thenBuildxRun(null, null, true);
}

@Test
Expand All @@ -87,7 +91,7 @@ void buildUsingConfiguredBuildx() throws IOException, MojoExecutionException {

whenMojoExecutes();

thenBuildxRun("src/docker/builder.toml", null);
thenBuildxRun("src/docker/builder.toml", null, true);
}

@Test
Expand All @@ -105,14 +109,32 @@ void buildUsingConfiguredBuildxWithContext() throws IOException, MojoExecutionEx

whenMojoExecutes();

thenBuildxRun(null, "src/main/docker");
thenBuildxRun(null, "src/main/docker", true);
}

@Test
void buildUsingBuildxWithNonNative() throws IOException, MojoExecutionException {
givenBuildXService();

givenMavenProject(buildMojo);
ImageConfiguration imageConfiguration = singleBuildXImageNonNative();
givenResolvedImages(buildMojo, Collections.singletonList(imageConfiguration));
givenPackaging("jar");

Mockito.doReturn(tmpDir.resolve("docker-build.tar").toFile())
.when(buildService)
.buildArchive(Mockito.any(), Mockito.any(), Mockito.any());

whenMojoExecutes();

thenBuildxRun(null, null, false);
}

private void givenBuildXService() {
BuildXService buildXService = new BuildXService(dockerAccess, dockerAssemblyManager, log, exec);

Mockito.doReturn(buildXService).when(serviceHub).getBuildXService();
Mockito.doReturn("linux/amd64").when(dockerAccess).getNativePlatform();
Mockito.doReturn(NATIVE_PLATFORM).when(dockerAccess).getNativePlatform();
}

private void thenBuildRun() throws DockerAccessException, MojoExecutionException {
Expand All @@ -128,7 +150,7 @@ private void verifyBuild(int wantedNumberOfInvocations) throws DockerAccessExcep
.buildImage(Mockito.any(ImageConfiguration.class), Mockito.any(ImagePullManager.class), Mockito.any(BuildService.BuildContext.class), Mockito.any());
}

private void thenBuildxRun(String relativeConfigFile, String contextDir) throws MojoExecutionException {
private void thenBuildxRun(String relativeConfigFile, String contextDir, boolean nativePlatformIncluded) throws MojoExecutionException {
Path buildPath = projectBaseDirectory.toPath().resolve("target/docker/example/latest");
String config = getOsDependentBuild(buildPath, "docker");
String cacheDir = getOsDependentBuild(buildPath, "cache");
Expand All @@ -146,19 +168,22 @@ private void thenBuildxRun(String relativeConfigFile, String contextDir) throws
ctxCmdLine = new String[] { buildDir };
} else {
Path contextPath = tmpDir.resolve("docker-build");
ctxCmdLine = new String[] { "--file=" + contextPath.resolve("Dockerfile"), contextPath.toString()};
ctxCmdLine = new String[] { "--file=" + contextPath.resolve("Dockerfile"), contextPath.toString() };
}

String platforms = nativePlatformIncluded ? NATIVE_PLATFORM + "," + NON_NATIVE_PLATFORM : NON_NATIVE_PLATFORM;
Mockito.verify(exec).process(Arrays.asList("docker", "--config", config, "buildx",
"build", "--progress=plain", "--builder", builderName,
"--platform", "linux/amd64,linux/arm64", "--tag", "example:latest", "--build-arg", "foo=bar",
"--platform", platforms, "--tag", "example:latest", "--build-arg", "foo=bar",
"--cache-to=type=local,dest=" + cacheDir, "--cache-from=type=local,src=" + cacheDir), ctxCmdLine);

Mockito.verify(exec).process(Arrays.asList("docker", "--config", config, "buildx",
"build", "--progress=plain", "--builder", builderName,
"--platform", "linux/amd64", "--tag", "example:latest", "--build-arg", "foo=bar",
"--load",
"--cache-to=type=local,dest=" + cacheDir, "--cache-from=type=local,src=" + cacheDir), ctxCmdLine);
if (nativePlatformIncluded) {
Mockito.verify(exec).process(Arrays.asList("docker", "--config", config, "buildx",
"build", "--progress=plain", "--builder", builderName,
"--platform", NATIVE_PLATFORM, "--tag", "example:latest", "--build-arg", "foo=bar",
"--load",
"--cache-to=type=local,dest=" + cacheDir, "--cache-from=type=local,src=" + cacheDir), ctxCmdLine);
}

Mockito.verify(exec).process(Arrays.asList("docker", "--config", config, "buildx"),
"rm", builderName);
Expand All @@ -175,4 +200,24 @@ private void givenSkipPom(boolean skipPom) {
private void whenMojoExecutes() throws IOException, MojoExecutionException {
buildMojo.executeInternal(serviceHub);
}

private BuildXConfiguration getBuildXConfiguration(String configFile, String... platforms) {
return new BuildXConfiguration.Builder()
.configFile(configFile)
.platforms(Arrays.asList(platforms))
.build();
}

private ImageConfiguration singleBuildXImageWithConfiguration(String configFile) {
return singleImageConfiguration(getBuildXConfiguration(configFile, TWO_BUILDX_PLATFORMS), null);
}

private ImageConfiguration singleBuildXImageWithContext(String contextDir) {
return singleImageConfiguration(getBuildXConfiguration(null, TWO_BUILDX_PLATFORMS), contextDir);
}

private ImageConfiguration singleBuildXImageNonNative() {
return singleImageConfiguration(getBuildXConfiguration(null, NON_NATIVE_PLATFORM), null);
}

}
17 changes: 1 addition & 16 deletions src/test/java/io/fabric8/maven/docker/MojoTestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,7 @@ protected ImageConfiguration singleImageWithBuild() {
return singleImageConfiguration(null, null);
}

protected ImageConfiguration singleBuildXImageWithConfiguration(String configFile) {
return singleImageConfiguration(getBuildXConfiguration(configFile), null);
}

protected ImageConfiguration singleBuildXImageWithContext(String contextDir) {
return singleImageConfiguration(getBuildXConfiguration(null), contextDir);
}

private BuildXConfiguration getBuildXConfiguration(String configFile) {
return new BuildXConfiguration.Builder()
.configFile(configFile)
.platforms(Arrays.asList("linux/amd64", "linux/arm64"))
.build();
}

private ImageConfiguration singleImageConfiguration(BuildXConfiguration buildx, String contextDir) {
ImageConfiguration singleImageConfiguration(BuildXConfiguration buildx, String contextDir) {
BuildImageConfiguration buildImageConfiguration = new BuildImageConfiguration.Builder()
.from("scratch")
.buildx(buildx)
Expand Down

0 comments on commit d5cc609

Please sign in to comment.