diff --git a/doc/changelog.md b/doc/changelog.md index fd02916ef..6f5c0ab86 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,5 +1,6 @@ # ChangeLog * **0.46-SNAPSHOT**: + - Make copy docker-buildx binary to temporary config directory work on windows too ([1819](https://github.com/fabric8io/docker-maven-plugin/pull/1819)) * **0.45.0 (2024-07-27)**: - Automatically create parent directories of portPropertyFile path ([1761](https://github.com/fabric8io/docker-maven-plugin/pull/1761)) diff --git a/src/main/java/io/fabric8/maven/docker/service/BuildXService.java b/src/main/java/io/fabric8/maven/docker/service/BuildXService.java index 1f63cd3e9..9bf5a228a 100644 --- a/src/main/java/io/fabric8/maven/docker/service/BuildXService.java +++ b/src/main/java/io/fabric8/maven/docker/service/BuildXService.java @@ -1,22 +1,5 @@ package io.fabric8.maven.docker.service; -import io.fabric8.maven.docker.access.AuthConfigList; -import io.fabric8.maven.docker.access.DockerAccess; -import io.fabric8.maven.docker.access.util.ExternalCommand; -import io.fabric8.maven.docker.assembly.BuildDirs; -import io.fabric8.maven.docker.assembly.DockerAssemblyManager; -import io.fabric8.maven.docker.config.AttestationConfiguration; -import io.fabric8.maven.docker.config.BuildImageConfiguration; -import io.fabric8.maven.docker.config.BuildXConfiguration; -import io.fabric8.maven.docker.config.ConfigHelper; -import io.fabric8.maven.docker.config.ImageConfiguration; -import io.fabric8.maven.docker.config.SecretConfiguration; -import io.fabric8.maven.docker.util.EnvUtil; -import io.fabric8.maven.docker.util.ImageName; -import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.ProjectPaths; -import org.apache.maven.plugin.MojoExecutionException; - import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -39,6 +22,24 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; +import org.apache.maven.plugin.MojoExecutionException; + +import io.fabric8.maven.docker.access.AuthConfigList; +import io.fabric8.maven.docker.access.DockerAccess; +import io.fabric8.maven.docker.access.util.ExternalCommand; +import io.fabric8.maven.docker.assembly.BuildDirs; +import io.fabric8.maven.docker.assembly.DockerAssemblyManager; +import io.fabric8.maven.docker.config.AttestationConfiguration; +import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.config.BuildXConfiguration; +import io.fabric8.maven.docker.config.ConfigHelper; +import io.fabric8.maven.docker.config.ImageConfiguration; +import io.fabric8.maven.docker.config.SecretConfiguration; +import io.fabric8.maven.docker.util.EnvUtil; +import io.fabric8.maven.docker.util.ImageName; +import io.fabric8.maven.docker.util.Logger; +import io.fabric8.maven.docker.util.ProjectPaths; + public class BuildXService { private static final String DOCKER = "docker"; private final DockerAccess dockerAccess; @@ -74,7 +75,6 @@ protected void useBuilder(ProjectPaths projectPaths, ImageConfiguration imag List buildX = new ArrayList<>(Arrays.asList(DOCKER, "--config", configPath.toString(), "buildx")); if (!isDockerBuildXWorkingWithOverriddenConfig(configPath)) { logger.debug("Detected current version of BuildX not working with --config override"); - logger.debug("Copying BuildX binary to " + configPath); copyBuildXToConfigPathIfBuildXBinaryInDefaultDockerConfig(configPath); } @@ -90,10 +90,12 @@ protected void useBuilder(ProjectPaths projectPaths, ImageConfiguration imag private void copyBuildXToConfigPathIfBuildXBinaryInDefaultDockerConfig(Path configPath) { try { - File buildXInUserHomeDockerConfig = Paths.get(EnvUtil.getUserHome(), ".docker/cli-plugins/docker-buildx").toFile(); + String dockerBuildxExecutableName = "docker-buildx" + (EnvUtil.isWindows()?".exe":""); + File buildXInUserHomeDockerConfig = Paths.get(EnvUtil.getUserHome(), ".docker/cli-plugins/" + dockerBuildxExecutableName).toFile(); Files.createDirectory(configPath.resolve("cli-plugins")); if (buildXInUserHomeDockerConfig.exists() && buildXInUserHomeDockerConfig.isFile()) { - Files.copy(buildXInUserHomeDockerConfig.toPath(), configPath.resolve("cli-plugins").resolve("docker-buildx"), StandardCopyOption.COPY_ATTRIBUTES); + Files.copy(buildXInUserHomeDockerConfig.toPath(), configPath.resolve("cli-plugins").resolve(dockerBuildxExecutableName), StandardCopyOption.COPY_ATTRIBUTES); + logger.debug("Copying BuildX binary to " + configPath); } } catch (IOException exception) { logger.debug(exception.getMessage()); diff --git a/src/test/java/io/fabric8/maven/docker/service/BuildXServiceTest.java b/src/test/java/io/fabric8/maven/docker/service/BuildXServiceTest.java index 5e35792da..eef98b335 100644 --- a/src/test/java/io/fabric8/maven/docker/service/BuildXServiceTest.java +++ b/src/test/java/io/fabric8/maven/docker/service/BuildXServiceTest.java @@ -1,57 +1,54 @@ package io.fabric8.maven.docker.service; -import io.fabric8.maven.docker.util.ImageName; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.io.File; -import java.nio.file.Paths; - -import io.fabric8.maven.docker.access.AuthConfig; import java.util.function.BiConsumer; -import io.fabric8.maven.docker.util.EnvUtil; import org.apache.maven.plugin.MojoExecutionException; import org.junit.jupiter.api.AfterEach; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockedConstruction; import org.mockito.MockedStatic; -import org.mockito.Spy; import org.mockito.Mockito; -import org.mockito.quality.Strictness; +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; -import io.fabric8.maven.docker.access.DockerAccess; +import io.fabric8.maven.docker.access.AuthConfig; import io.fabric8.maven.docker.access.AuthConfigList; +import io.fabric8.maven.docker.access.DockerAccess; import io.fabric8.maven.docker.assembly.DockerAssemblyManager; -import io.fabric8.maven.docker.util.Logger; -import io.fabric8.maven.docker.util.ProjectPaths; -import io.fabric8.maven.docker.config.BuildXConfiguration; import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.config.BuildXConfiguration; import io.fabric8.maven.docker.config.ImageConfiguration; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mockConstruction; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import io.fabric8.maven.docker.util.EnvUtil; +import io.fabric8.maven.docker.util.ImageName; +import io.fabric8.maven.docker.util.Logger; +import io.fabric8.maven.docker.util.ProjectPaths; @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) @@ -238,10 +235,11 @@ void useBuilder_whenConfiguredRegistryAbsentInDockerRegistry_thenAddConfigOption assertEquals(Arrays.asList("docker", "--config", temporaryFolder.getAbsolutePath(), "buildx"), buildXArgCaptor.getValue()); } - @Test - void useBuilder_whenDockerBuildXIncompatibleWithConfigOverride_thenCopyBuildXBinaryToTemporaryConfig() throws IOException, MojoExecutionException { + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void useBuilder_whenDockerBuildXIncompatibleWithConfigOverride_thenCopyBuildXBinaryToTemporaryConfig(boolean isWindows) throws IOException, MojoExecutionException { try (MockedStatic envUtilMockedStatic = mockStatic(EnvUtil.class); - MockedConstruction ignore = mockConstruction(BuildXService.BuildXListWithConfigCommand.class, (mock, ctx) -> { + MockedConstruction ignore = mockConstruction(BuildXService.BuildXListWithConfigCommand.class, (mock, ctx) -> { when(mock.isSuccessFul()).thenReturn(false); })) { // Given @@ -249,9 +247,12 @@ void useBuilder_whenDockerBuildXIncompatibleWithConfigOverride_thenCopyBuildXBin Files.createDirectory(configDirPath); Files.createDirectory(temporaryFolder.toPath().resolve(".docker")); Files.createDirectory(temporaryFolder.toPath().resolve(".docker").resolve("cli-plugins")); - Files.createFile(temporaryFolder.toPath().resolve(".docker").resolve("cli-plugins").resolve("docker-buildx")); + final String buildxExecutableFilename = "docker-buildx" + (isWindows ? ".exe" : ""); + Files.createFile(temporaryFolder.toPath().resolve(".docker").resolve("cli-plugins").resolve(buildxExecutableFilename)); envUtilMockedStatic.when(EnvUtil::getUserHome).thenReturn(temporaryFolder.getAbsolutePath()); + envUtilMockedStatic.when(EnvUtil::isWindows).thenReturn(isWindows); BuildXService.Builder builder = Mockito.mock(BuildXService.Builder.class); + givenAnImageConfiguration("linux/arm46", "linux/amd64"); // When @@ -259,7 +260,7 @@ void useBuilder_whenDockerBuildXIncompatibleWithConfigOverride_thenCopyBuildXBin // Then assertTrue(configDirPath.resolve("cli-plugins").toFile().exists()); - assertTrue(configDirPath.resolve("cli-plugins").resolve("docker-buildx").toFile().exists()); + assertTrue(configDirPath.resolve("cli-plugins").resolve(buildxExecutableFilename).toFile().exists()); verify(logger).debug("Detected current version of BuildX not working with --config override"); verify(logger).debug("Copying BuildX binary to " + temporaryFolder.toPath().resolve("docker-state-dir")); }