Skip to content

Commit

Permalink
fix : AuthConfigList is populated with from images during buildx push…
Browse files Browse the repository at this point in the history
… as well

Signed-off-by: Rohan Kumar <[email protected]>
  • Loading branch information
rohanKanojia committed Feb 11, 2024
1 parent f58346e commit 4935994
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 120 deletions.
1 change: 1 addition & 0 deletions doc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- The <noCache> option is now propagated down to the buildx command, if it is set in the <build> 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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> buildArgs;

@Parameter(property = "docker.pull.registry")
String pullRegistry;

@Parameter( defaultValue = "${reactorProjects}", required = true, readonly = true )
private List<MavenProject> reactorProjects;


protected BuildService.BuildContext getBuildContext() throws MojoExecutionException {
return new BuildService.BuildContext.Builder()
Expand All @@ -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);
}

}
23 changes: 23 additions & 0 deletions src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<MavenProject> reactorProjects;
@Parameter
protected MavenArchiveConfiguration archive;

@Component
protected MavenFileFilter mavenFileFilter;

@Component
protected MavenReaderFilter mavenFilterReader;

@Parameter
protected Map<String, String> buildArgs;

// Images resolved with external image resolvers and hooks for subclass to
// mangle the image configurations.
List<ImageConfiguration> resolvedImages;
Expand Down Expand Up @@ -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);
}
}
106 changes: 14 additions & 92 deletions src/main/java/io/fabric8/maven/docker/BuildMojo.java
Original file line number Diff line number Diff line change
@@ -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
*
Expand Down Expand Up @@ -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) {
Expand All @@ -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<String> 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<String> getRegistriesForPull(BuildImageConfiguration buildConfig) {
Set<String> registries = new HashSet<>();
List<String> fromImages = extractBaseFromDockerfile(buildConfig);
for (String fromImage : fromImages) {
ImageName imageName = new ImageName(fromImage);

if (imageName.hasRegistry()) {
registries.add(imageName.getRegistry());
}
}
return registries;
}

private List<String> 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<String> 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();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/fabric8/maven/docker/PushMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
82 changes: 78 additions & 4 deletions src/main/java/io/fabric8/maven/docker/service/RegistryService.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -50,7 +58,7 @@ public class RegistryService {
* @throws MojoExecutionException
*/
public void pushImages(ProjectPaths projectPaths, Collection<ImageConfiguration> 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()) {
Expand All @@ -66,12 +74,13 @@ public void pushImages(ProjectPaths projectPaths, Collection<ImageConfiguration>
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);
}
}
}
Expand Down Expand Up @@ -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<String> 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<String> getRegistriesForPull(BuildImageConfiguration buildConfig, MojoParameters mojoParameters) {
Set<String> registries = new HashSet<>();
List<String> 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<String> 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<String> fromImage;
try {
File fullDockerFilePath = buildConfig.getAbsoluteDockerFilePath(mojoParameters);
fromImage = DockerFileUtil.extractBaseImages(
fullDockerFilePath,
DockerFileUtil.createInterpolator(mojoParameters, buildConfig.getFilter()),
buildConfig.getArgs());
} catch (IOException e) {
return Collections.emptyList();

Check warning on line 212 in src/main/java/io/fabric8/maven/docker/service/RegistryService.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/io/fabric8/maven/docker/service/RegistryService.java#L211-L212

Added lines #L211 - L212 were not covered by tests
}
return fromImage;
}

private boolean imageRequiresPull(boolean hasImage, ImagePullPolicy pullPolicy, String imageName)
throws MojoExecutionException {
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/io/fabric8/maven/docker/PushMojoTest.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.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;
Expand Down Expand Up @@ -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 {
Expand Down
Loading

0 comments on commit 4935994

Please sign in to comment.