From 076f114b0b09851c439551e98f3d0c3e4b5a90b9 Mon Sep 17 00:00:00 2001 From: Rohan Kumar Date: Mon, 5 Feb 2024 23:53:43 +0530 Subject: [PATCH] fix : AuthConfigList is populated with from images during buildx push as well Signed-off-by: Rohan Kumar --- doc/changelog.md | 1 + .../docker/AbstractBuildSupportMojo.java | 21 --- .../maven/docker/AbstractDockerMojo.java | 23 +++ .../io/fabric8/maven/docker/BuildMojo.java | 106 ++----------- .../io/fabric8/maven/docker/PushMojo.java | 2 +- .../maven/docker/service/RegistryService.java | 82 +++++++++- .../io/fabric8/maven/docker/PushMojoTest.java | 3 +- .../RegistryServicePushImagesBuildXTest.java | 143 ++++++++++++++++++ .../docker/service/RegistryServiceTest.java | 2 +- 9 files changed, 263 insertions(+), 120 deletions(-) create mode 100644 src/test/java/io/fabric8/maven/docker/service/RegistryServicePushImagesBuildXTest.java diff --git a/doc/changelog.md b/doc/changelog.md index 3e7d90f93..ae6bdc335 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -4,6 +4,7 @@ - The option is now propagated down to the buildx command, if it is set in the section. ([1717](https://github.com/fabric8io/docker-maven-plugin/pull/1717)) - Fix Buildx build with Dockerfile outside of the Docker build context directory ([1721](https://github.com/fabric8io/docker-maven-plugin/pull/1721)) - Add support setting driverOpts for buildx ([1704](https://github.com/fabric8io/docker-maven-plugin/pull/1704)) + - Multi-Architecture push is not sending pull registry auth credentials ([1709](https://github.com/fabric8io/docker-maven-plugin/issues/1709)) * **0.43.4** (2023-08-18): - Always pass `--config` option for latest versions of Docker CLI ([1701](https://github.com/fabric8io/docker-maven-plugin/issues/1701)) diff --git a/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java b/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java index ceea2e5ce..75c251a6d 100644 --- a/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java +++ b/src/main/java/io/fabric8/maven/docker/AbstractBuildSupportMojo.java @@ -23,25 +23,9 @@ abstract public class AbstractBuildSupportMojo extends AbstractDockerMojo { // Parameters required from Maven when building an assembly. They cannot be injected directly // into DockerAssemblyCreator. // See also here: http://maven.40175.n5.nabble.com/Mojo-Java-1-5-Component-MavenProject-returns-null-vs-JavaDoc-parameter-expression-quot-project-quot-s-td5733805.html - - @Parameter - private MavenArchiveConfiguration archive; - - @Component - private MavenFileFilter mavenFileFilter; - - @Component - private MavenReaderFilter mavenFilterReader; - - @Parameter - private Map buildArgs; - @Parameter(property = "docker.pull.registry") String pullRegistry; - @Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true ) - private List reactorProjects; - protected BuildService.BuildContext getBuildContext() throws MojoExecutionException { return new BuildService.BuildContext.Builder() @@ -51,9 +35,4 @@ protected BuildService.BuildContext getBuildContext() throws MojoExecutionExcept .build(); } - protected MojoParameters createMojoParameters() { - return new MojoParameters(session, project, archive, mavenFileFilter, mavenFilterReader, - settings, sourceDirectory, outputDirectory, reactorProjects); - } - } diff --git a/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java b/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java index cde5d49d3..6ff31c1e4 100644 --- a/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java +++ b/src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java @@ -37,9 +37,11 @@ import io.fabric8.maven.docker.util.EnvUtil; import io.fabric8.maven.docker.util.GavLabel; import io.fabric8.maven.docker.util.ImageNameFormatter; +import io.fabric8.maven.docker.util.MojoParameters; import io.fabric8.maven.docker.util.NamePatternUtil; import io.fabric8.maven.docker.util.ProjectPaths; +import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecution; @@ -49,6 +51,8 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.settings.Settings; +import org.apache.maven.shared.filtering.MavenFileFilter; +import org.apache.maven.shared.filtering.MavenReaderFilter; import org.apache.maven.shared.utils.logging.MessageUtils; import org.codehaus.plexus.PlexusConstants; import org.codehaus.plexus.PlexusContainer; @@ -225,6 +229,20 @@ public abstract class AbstractDockerMojo extends AbstractMojo implements Context @Parameter(property = "docker.skip.pom", defaultValue = "false") protected boolean skipPom; + @Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true ) + protected List reactorProjects; + @Parameter + protected MavenArchiveConfiguration archive; + + @Component + protected MavenFileFilter mavenFileFilter; + + @Component + protected MavenReaderFilter mavenFilterReader; + + @Parameter + protected Map buildArgs; + // Images resolved with external image resolvers and hooks for subclass to // mangle the image configurations. List resolvedImages; @@ -608,4 +626,9 @@ private String determinePullPolicy(RunImageConfiguration runConfig) { protected ProjectPaths createProjectPaths() { return new ProjectPaths(project.getBasedir(), outputDirectory); } + + protected MojoParameters createMojoParameters() { + return new MojoParameters(session, project, archive, mavenFileFilter, mavenFilterReader, + settings, sourceDirectory, outputDirectory, reactorProjects); + } } diff --git a/src/main/java/io/fabric8/maven/docker/BuildMojo.java b/src/main/java/io/fabric8/maven/docker/BuildMojo.java index 5dc5ce7cc..f703e4a0d 100644 --- a/src/main/java/io/fabric8/maven/docker/BuildMojo.java +++ b/src/main/java/io/fabric8/maven/docker/BuildMojo.java @@ -1,41 +1,32 @@ package io.fabric8.maven.docker; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.Collections; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import io.fabric8.maven.docker.access.AuthConfig; -import io.fabric8.maven.docker.access.AuthConfigList; import io.fabric8.maven.docker.access.DockerAccessException; import io.fabric8.maven.docker.config.BuildImageConfiguration; import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.service.BuildService; import io.fabric8.maven.docker.service.ImagePullManager; import io.fabric8.maven.docker.service.JibBuildService; -import io.fabric8.maven.docker.service.RegistryService; import io.fabric8.maven.docker.service.ServiceHub; -import io.fabric8.maven.docker.util.DockerFileUtil; -import io.fabric8.maven.docker.util.ImageName; -import io.fabric8.maven.docker.util.Logger; import io.fabric8.maven.docker.util.EnvUtil; -import io.fabric8.maven.docker.util.MojoParameters; -import org.apache.commons.lang3.StringUtils; +import io.fabric8.maven.docker.util.Logger; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.Date; +import java.util.Enumeration; + +import static io.fabric8.maven.docker.service.RegistryService.createCompleteAuthConfigList; + /** * Mojo for building a data image * @@ -110,7 +101,7 @@ private void proceedWithDockerBuild(ServiceHub hub, BuildService.BuildContext bu File buildArchiveFile = buildService.buildArchive(imageConfig, buildContext, resolveBuildArchiveParameter()); if (Boolean.FALSE.equals(shallBuildArchiveOnly())) { if (imageConfig.isBuildX()) { - hub.getBuildXService().build(createProjectPaths(), imageConfig, null, getAuthConfig(imageConfig), buildArchiveFile); + hub.getBuildXService().build(createProjectPaths(), imageConfig, null, createCompleteAuthConfigList(false, imageConfig, getRegistryConfig(pullRegistry), createMojoParameters()), buildArchiveFile); } else { buildService.buildImage(imageConfig, pullManager, buildContext, buildArchiveFile); if (!skipTag) { @@ -120,76 +111,7 @@ private void proceedWithDockerBuild(ServiceHub hub, BuildService.BuildContext bu } } - - private AuthConfigList getAuthConfig(ImageConfiguration imageConfig) throws MojoExecutionException { - // TODO: refactor similar code in RegistryService#pushImages - RegistryService.RegistryConfig registryConfig = getRegistryConfig(pullRegistry); - - ImageName imageName = new ImageName(imageConfig.getName()); - String configuredRegistry = EnvUtil.firstRegistryOf( - imageName.getRegistry(), - imageConfig.getRegistry(), - registryConfig.getRegistry()); - - AuthConfig authConfig = registryConfig.createAuthConfig(false, imageName.getUser(), configuredRegistry); - AuthConfigList authConfigList = new AuthConfigList(); - if (authConfig != null) { - authConfigList.addAuthConfig(authConfig); - } - - BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); - Set fromRegistries = getRegistriesForPull(buildConfig); - for (String fromRegistry : fromRegistries) { - if (StringUtils.isNotBlank(configuredRegistry) && configuredRegistry.equalsIgnoreCase(fromRegistry)) { - continue; - } - registryConfig = getRegistryConfig(fromRegistry); - AuthConfig additionalAuth = registryConfig.createAuthConfig(false, imageName.getUser(), fromRegistry); - if (additionalAuth != null) { - authConfigList.addAuthConfig(additionalAuth); - } - } - - return authConfigList; - } - - private Set getRegistriesForPull(BuildImageConfiguration buildConfig) { - Set registries = new HashSet<>(); - List fromImages = extractBaseFromDockerfile(buildConfig); - for (String fromImage : fromImages) { - ImageName imageName = new ImageName(fromImage); - - if (imageName.hasRegistry()) { - registries.add(imageName.getRegistry()); - } - } - return registries; - } - - private List extractBaseFromDockerfile(BuildImageConfiguration buildConfig) { - if (buildConfig.getDockerFile() == null || !buildConfig.getDockerFile().exists()) { - if (buildConfig.getFrom() != null && !buildConfig.getFrom().isEmpty()) { - return Collections.singletonList(buildConfig.getFrom()); - } - return Collections.emptyList(); - } - - List fromImage; - try { - MojoParameters mojoParameters = createMojoParameters(); - File fullDockerFilePath = buildConfig.getAbsoluteDockerFilePath(mojoParameters); - fromImage = DockerFileUtil.extractBaseImages( - fullDockerFilePath, - DockerFileUtil.createInterpolator(mojoParameters, buildConfig.getFilter()), - buildConfig.getArgs()); - } catch (IOException e) { - return Collections.emptyList(); - } - return fromImage; - } - // We ignore an already existing date file and always return the current date - @Override protected Date getReferenceDate() { return new Date(); diff --git a/src/main/java/io/fabric8/maven/docker/PushMojo.java b/src/main/java/io/fabric8/maven/docker/PushMojo.java index 0797a6e3e..01acdab1a 100644 --- a/src/main/java/io/fabric8/maven/docker/PushMojo.java +++ b/src/main/java/io/fabric8/maven/docker/PushMojo.java @@ -51,7 +51,7 @@ public void executeInternal(ServiceHub hub) throws DockerAccessException, MojoEx } private void executeDockerPush(ServiceHub hub) throws MojoExecutionException, DockerAccessException { - hub.getRegistryService().pushImages(createProjectPaths(), getResolvedImages(), retries, getRegistryConfig(pushRegistry), skipTag); + hub.getRegistryService().pushImages(createProjectPaths(), getResolvedImages(), retries, getRegistryConfig(pushRegistry), skipTag, createMojoParameters()); } private void executeJibPush(ServiceHub hub) throws MojoExecutionException { diff --git a/src/main/java/io/fabric8/maven/docker/service/RegistryService.java b/src/main/java/io/fabric8/maven/docker/service/RegistryService.java index 30633f91b..efef542bc 100644 --- a/src/main/java/io/fabric8/maven/docker/service/RegistryService.java +++ b/src/main/java/io/fabric8/maven/docker/service/RegistryService.java @@ -1,9 +1,14 @@ package io.fabric8.maven.docker.service; +import java.io.File; +import java.io.IOException; import java.io.Serializable; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; import io.fabric8.maven.docker.access.AuthConfig; import io.fabric8.maven.docker.access.AuthConfigList; @@ -14,11 +19,14 @@ import io.fabric8.maven.docker.config.ImageConfiguration; import io.fabric8.maven.docker.config.ImagePullPolicy; import io.fabric8.maven.docker.util.AuthConfigFactory; +import io.fabric8.maven.docker.util.DockerFileUtil; 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.MojoParameters; import io.fabric8.maven.docker.util.ProjectPaths; +import org.apache.commons.lang3.StringUtils; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.settings.Settings; @@ -50,7 +58,7 @@ public class RegistryService { * @throws MojoExecutionException */ public void pushImages(ProjectPaths projectPaths, Collection imageConfigs, - int retries, RegistryConfig registryConfig, boolean skipTag) throws DockerAccessException, MojoExecutionException { + int retries, RegistryConfig registryConfig, boolean skipTag, MojoParameters mojoParameters) throws DockerAccessException, MojoExecutionException { for (ImageConfiguration imageConfig : imageConfigs) { BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration(); if (buildConfig == null || buildConfig.skipPush()) { @@ -66,12 +74,13 @@ public void pushImages(ProjectPaths projectPaths, Collection imageConfig.getRegistry(), registryConfig.getRegistry()); + AuthConfig authConfigForLegacyPush = createAuthConfig(true, imageName.getUser(), configuredRegistry, registryConfig); + AuthConfigList authConfigListForBuildXPush = createCompleteAuthConfigList(true, imageConfig, registryConfig, mojoParameters); - AuthConfig authConfig = createAuthConfig(true, imageName.getUser(), configuredRegistry, registryConfig); if (imageConfig.isBuildX()) { - buildXService.push(projectPaths, imageConfig, configuredRegistry, new AuthConfigList(authConfig)); + buildXService.push(projectPaths, imageConfig, configuredRegistry, authConfigListForBuildXPush); } else { - dockerPush(retries, skipTag, buildConfig, name, configuredRegistry, authConfig); + dockerPush(retries, skipTag, buildConfig, name, configuredRegistry, authConfigForLegacyPush); } } } @@ -137,8 +146,73 @@ public void pullImageWithPolicy(String image, ImagePullManager pullManager, Regi } + public static AuthConfigList createCompleteAuthConfigList(boolean isPush, ImageConfiguration imageConfig, RegistryConfig registryConfig, MojoParameters mojoParameters) throws MojoExecutionException { + ImageName imageName = new ImageName(imageConfig.getName()); + String configuredRegistry = EnvUtil.firstRegistryOf( + imageName.getRegistry(), + imageConfig.getRegistry(), + registryConfig.getRegistry()); + + AuthConfig authConfig = registryConfig.createAuthConfig(isPush, imageName.getUser(), configuredRegistry); + AuthConfigList authConfigList = createAuthConfigListForBaseImages(imageConfig.getBuildConfiguration(), mojoParameters, configuredRegistry, registryConfig); + if (authConfig != null) { + authConfigList.addAuthConfig(authConfig); + } + + return authConfigList; + } + + public static AuthConfigList createAuthConfigListForBaseImages(BuildImageConfiguration buildConfig, MojoParameters mojoParameters, String configuredRegistry, RegistryConfig registryConfig) throws MojoExecutionException { + AuthConfigList authConfigList = new AuthConfigList(); + Set fromRegistries = getRegistriesForPull(buildConfig, mojoParameters); + for (String fromRegistry : fromRegistries) { + if (StringUtils.isNotBlank(configuredRegistry) && configuredRegistry.equalsIgnoreCase(fromRegistry)) { + continue; + } + registryConfig.registry = fromRegistry; + AuthConfig additionalAuth = registryConfig.createAuthConfig(false, null, fromRegistry); + if (additionalAuth != null) { + authConfigList.addAuthConfig(additionalAuth); + } + } + return authConfigList; + } + // ============================================================================================================ + private static Set getRegistriesForPull(BuildImageConfiguration buildConfig, MojoParameters mojoParameters) { + Set registries = new HashSet<>(); + List fromImages = extractBaseFromDockerfile(buildConfig, mojoParameters); + for (String fromImage : fromImages) { + ImageName imageName = new ImageName(fromImage); + + if (imageName.hasRegistry()) { + registries.add(imageName.getRegistry()); + } + } + return registries; + } + + private static List extractBaseFromDockerfile(BuildImageConfiguration buildConfig, MojoParameters mojoParameters) { + if (buildConfig.getDockerFile() == null || !buildConfig.getDockerFile().exists()) { + if (buildConfig.getFrom() != null && !buildConfig.getFrom().isEmpty()) { + return Collections.singletonList(buildConfig.getFrom()); + } + return Collections.emptyList(); + } + + List fromImage; + try { + File fullDockerFilePath = buildConfig.getAbsoluteDockerFilePath(mojoParameters); + fromImage = DockerFileUtil.extractBaseImages( + fullDockerFilePath, + DockerFileUtil.createInterpolator(mojoParameters, buildConfig.getFilter()), + buildConfig.getArgs()); + } catch (IOException e) { + return Collections.emptyList(); + } + return fromImage; + } private boolean imageRequiresPull(boolean hasImage, ImagePullPolicy pullPolicy, String imageName) throws MojoExecutionException { diff --git a/src/test/java/io/fabric8/maven/docker/PushMojoTest.java b/src/test/java/io/fabric8/maven/docker/PushMojoTest.java index 47e78c3b7..2036aa2a7 100644 --- a/src/test/java/io/fabric8/maven/docker/PushMojoTest.java +++ b/src/test/java/io/fabric8/maven/docker/PushMojoTest.java @@ -2,6 +2,7 @@ import io.fabric8.maven.docker.access.DockerAccessException; import io.fabric8.maven.docker.service.RegistryService; +import io.fabric8.maven.docker.util.MojoParameters; import io.fabric8.maven.docker.util.ProjectPaths; import org.apache.maven.plugin.MojoExecutionException; import org.junit.jupiter.api.Test; @@ -81,7 +82,7 @@ private void thenImageNotPushed() throws DockerAccessException, MojoExecutionExc private void verifyPush(int wantedNumberOfInvocations) throws DockerAccessException, MojoExecutionException { Mockito.verify(registryService, Mockito.times(wantedNumberOfInvocations)) - .pushImages(Mockito.any(ProjectPaths.class), Mockito.anyCollection(), Mockito.anyInt(), Mockito.any(RegistryService.RegistryConfig.class), Mockito.anyBoolean()); + .pushImages(Mockito.any(ProjectPaths.class), Mockito.anyCollection(), Mockito.anyInt(), Mockito.any(RegistryService.RegistryConfig.class), Mockito.anyBoolean(), Mockito.any(MojoParameters.class)); } private void whenMojoExecutes() throws IOException, MojoExecutionException { diff --git a/src/test/java/io/fabric8/maven/docker/service/RegistryServicePushImagesBuildXTest.java b/src/test/java/io/fabric8/maven/docker/service/RegistryServicePushImagesBuildXTest.java new file mode 100644 index 000000000..3060e6bf1 --- /dev/null +++ b/src/test/java/io/fabric8/maven/docker/service/RegistryServicePushImagesBuildXTest.java @@ -0,0 +1,143 @@ +package io.fabric8.maven.docker.service; + +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.access.DockerAccessException; +import io.fabric8.maven.docker.config.BuildImageConfiguration; +import io.fabric8.maven.docker.config.BuildXConfiguration; +import io.fabric8.maven.docker.config.ImageConfiguration; +import io.fabric8.maven.docker.util.AuthConfigFactory; +import io.fabric8.maven.docker.util.Logger; +import io.fabric8.maven.docker.util.ProjectPaths; +import org.apache.maven.plugin.MojoExecutionException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.ArgumentCaptor; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class RegistryServicePushImagesBuildXTest { + private RegistryService registryService; + private BuildXService buildXService; + private List imageConfigurationList; + private ProjectPaths projectPaths; + private RegistryService.RegistryConfig registryConfig; + private AuthConfigFactory authConfigFactory; + + @TempDir + private File temporaryFolder; + + @BeforeEach + void setUp() { + buildXService = mock(BuildXService.class); + Logger logger = mock(Logger.class); + authConfigFactory = mock(AuthConfigFactory.class); + DockerAccess dockerAccess = mock(DockerAccess.class); + QueryService queryService = new QueryService(dockerAccess); + imageConfigurationList = Collections.singletonList(createNewImageConfiguration("user1/sample-image:latest", "foo/base:latest", null)); + registryConfig = new RegistryService.RegistryConfig.Builder() + .registry("registry1.org") + .authConfigFactory(authConfigFactory) + .build(); + projectPaths = new ProjectPaths(temporaryFolder, "target/docker"); + registryService = new RegistryService(dockerAccess, queryService, buildXService, logger); + } + + @Test + void whenNoRegistryConfigured_thenAuthConfigEmpty() throws MojoExecutionException, DockerAccessException { + // When + registryService.pushImages(projectPaths, imageConfigurationList, 0, registryConfig, false, null); + + // Then + verifyBuildXServiceInvokedWithAuthConfigListSize(0); + } + + @Test + void whenOnlyPushRegistryConfigured_thenAuthConfigHasSingleEntry() throws MojoExecutionException, DockerAccessException { + // Given + givenAuthConfigExistsForRegistry("registry1.org", "user1", "password1"); + + // When + registryService.pushImages(projectPaths, imageConfigurationList, 0, registryConfig, false, null); + + // Then + verifyBuildXServiceInvokedWithAuthConfigListSize(1); + } + + @Test + void whenFromRegistryAndPushRegistryProvided_thenAuthConfigListContainsEntriesForBothPullAndPush() throws MojoExecutionException, DockerAccessException { + // Given + imageConfigurationList = Collections.singletonList(createNewImageConfiguration("user1/base-image-different-registry:latest", "registry2.org/user2/base:latest", null)); + givenAuthConfigExistsForRegistry("registry1.org", "user1", "password1"); + givenAuthConfigExistsForRegistry("registry2.org", "user2", "password2"); + + // When + registryService.pushImages(projectPaths, imageConfigurationList, 0, registryConfig, false, null); + + // Then + verifyBuildXServiceInvokedWithAuthConfigListSize(2); + } + + @Test + void whenDockerfileContainsFromReferencingMultipleRegistries_thenAuthConfigListContainsMultipleEntries() throws MojoExecutionException, IOException { + // Given + File dockerFile = new File(temporaryFolder, "Dockerfile"); + Files.write(dockerFile.toPath(), String.format("FROM registry2.org/user2/test-base:latest%n").getBytes()); + Files.write(dockerFile.toPath(), "FROM registry3.org/user3/scratch:1.0 AS build2".getBytes(), StandardOpenOption.APPEND); + imageConfigurationList = Collections.singletonList(createNewImageConfiguration("user1/base-image-different-registry:latest", null, dockerFile)); + givenAuthConfigExistsForRegistry("registry1.org", "user1", "password1"); + givenAuthConfigExistsForRegistry("registry2.org", "user2", "password2"); + givenAuthConfigExistsForRegistry("registry3.org", "user3", "password2"); + + // When + registryService.pushImages(projectPaths, imageConfigurationList, 0, registryConfig, false, null); + + // Then + verifyBuildXServiceInvokedWithAuthConfigListSize(3); + } + + private void verifyBuildXServiceInvokedWithAuthConfigListSize(int expectedSize) throws MojoExecutionException { + ArgumentCaptor authConfigListArgumentCaptor = ArgumentCaptor.forClass(AuthConfigList.class); + verify(buildXService).push(any(), any(), anyString(), authConfigListArgumentCaptor.capture()); + assertEquals(expectedSize, authConfigListArgumentCaptor.getValue().size()); + } + + private void givenAuthConfigExistsForRegistry(String registry, String username, String password) throws MojoExecutionException { + AuthConfig auth = new AuthConfig(username, password, null, null); + auth.setRegistry(registry); + + when(authConfigFactory.createAuthConfig(anyBoolean(), anyBoolean(), any(), any(), any(), eq(registry))) + .thenReturn(auth); + } + + private ImageConfiguration createNewImageConfiguration(String name, String from, File dockerFile) { + BuildImageConfiguration buildImageConfiguration = mock(BuildImageConfiguration.class); + when(buildImageConfiguration.getFrom()).thenReturn(from); + when(buildImageConfiguration.getBuildX()).thenReturn(new BuildXConfiguration.Builder() + .platforms(Arrays.asList("linux/amd64", "linux/arm64")) + .build()); + when(buildImageConfiguration.isBuildX()).thenReturn(true); + when(buildImageConfiguration.getDockerFile()).thenReturn(dockerFile); + when(buildImageConfiguration.getAbsoluteDockerFilePath(any())).thenReturn(dockerFile); + return new ImageConfiguration.Builder() + .name(name) + .buildConfig(buildImageConfiguration).build(); + } +} diff --git a/src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java b/src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java index ebddf0b59..9b19871b1 100644 --- a/src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java +++ b/src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java @@ -539,7 +539,7 @@ private void whenPushImage() { .authConfig(authConfig) .registry(registry) .build(); - registryService.pushImages(projectPaths, Collections.singleton(imageConfiguration), 1, registryConfig, false); + registryService.pushImages(projectPaths, Collections.singleton(imageConfiguration), 1, registryConfig, false, null); } catch (Exception e) { this.actualException = e; }