Skip to content

Commit

Permalink
fix: multi-arch build should use provided repository
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Merikan <[email protected]>
  • Loading branch information
merikan authored and rohanKanojia committed Jan 12, 2023
1 parent a1090e0 commit 01c0b85
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 29 deletions.
1 change: 1 addition & 0 deletions doc/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# ChangeLog
* **0.41-SNAPSHOT** :
- multi-arch build should use provided repository ([1597](https://github.com/fabric8io/docker-maven-plugin/issues/1597)) @merikan

* **0.40.3** (2022-12-18):
- image/squash option is taken into account when using buildx ([1605](https://github.com/fabric8io/docker-maven-plugin/pull/1605)) @kevinleturc
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/fabric8/maven/docker/BuildMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,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, getAuthConfig(imageConfig), buildArchiveFile);
hub.getBuildXService().build(createProjectPaths(), imageConfig, null, getAuthConfig(imageConfig), buildArchiveFile);
} else {
buildService.buildImage(imageConfig, pullManager, buildContext, buildArchiveFile);
if (!skipTag) {
Expand Down
28 changes: 14 additions & 14 deletions src/main/java/io/fabric8/maven/docker/service/BuildXService.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ public BuildXService(DockerAccess dockerAccess, DockerAssemblyManager dockerAsse
this.exec = exec;
}

public void build(ProjectPaths projectPaths, ImageConfiguration imageConfig, AuthConfig authConfig, File buildArchive) throws MojoExecutionException {
useBuilder(projectPaths, imageConfig, authConfig, buildArchive, this::buildAndLoadNativePlatform);
public void build(ProjectPaths projectPaths, ImageConfiguration imageConfig, String configuredRegistry, AuthConfig authConfig, File buildArchive) throws MojoExecutionException {
useBuilder(projectPaths, imageConfig, configuredRegistry, authConfig, buildArchive, this::buildAndLoadNativePlatform);
}

public void push(ProjectPaths projectPaths, ImageConfiguration imageConfig, AuthConfig authConfig) throws MojoExecutionException {
public void push(ProjectPaths projectPaths, ImageConfiguration imageConfig, String configuredRegistry, AuthConfig authConfig) throws MojoExecutionException {
BuildDirs buildDirs = new BuildDirs(projectPaths, imageConfig.getName());
File archive = new File(buildDirs.getTemporaryRootDirectory(), "docker-build.tar");
useBuilder(projectPaths, imageConfig, authConfig, archive, this::pushMultiPlatform);
useBuilder(projectPaths, imageConfig, configuredRegistry, authConfig, archive, this::pushMultiPlatform);
}

private <C> void useBuilder(ProjectPaths projectPaths, ImageConfiguration imageConfig, AuthConfig authConfig, C context, Builder<C> builder) throws MojoExecutionException {
private <C> void useBuilder(ProjectPaths projectPaths, ImageConfiguration imageConfig, String configuredRegistry, AuthConfig authConfig, C context, Builder<C> builder) throws MojoExecutionException {
BuildDirs buildDirs = new BuildDirs(projectPaths, imageConfig.getName());

Path configPath = getDockerStateDir(imageConfig.getBuildConfiguration(), buildDirs);
Expand All @@ -68,7 +68,7 @@ private <C> void useBuilder(ProjectPaths projectPaths, ImageConfiguration imageC
Path configJson = configPath.resolve("config.json");
try {
createConfigJson(configJson, authConfig);
builder.useBuilder(buildX, builderName, buildDirs, imageConfig, context);
builder.useBuilder(buildX, builderName, buildDirs, imageConfig, configuredRegistry, context);
} finally {
removeConfigJson(configJson);
}
Expand All @@ -92,23 +92,23 @@ private void removeConfigJson(Path configJson) {
}
}

private void buildAndLoadNativePlatform(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, File buildArchive) throws MojoExecutionException {
private void buildAndLoadNativePlatform(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, String configuredRegistry, File buildArchive) throws MojoExecutionException {
List<String> platforms = imageConfig.getBuildConfiguration().getBuildX().getPlatforms();
// build and 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");
buildX(buildX, builderName, buildDirs, imageConfig, configuredRegistry, Collections.singletonList(nativePlatform), buildArchive, "--load");
} else {
logger.info("Native platform not specified, no image built");
}
}

private void pushMultiPlatform(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, File buildArchive) throws MojoExecutionException {
private void pushMultiPlatform(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, String configuredRegistry, File buildArchive) throws MojoExecutionException {
// build and push all images. The native platform may be re-built, image should be cached and build should be quick
buildX(buildX, builderName, buildDirs, imageConfig, imageConfig.getBuildConfiguration().getBuildX().getPlatforms(), buildArchive, "--push");
buildX(buildX, builderName, buildDirs, imageConfig, configuredRegistry, imageConfig.getBuildConfiguration().getBuildX().getPlatforms(), buildArchive, "--push");
}

private void buildX(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, List<String> platforms, File buildArchive, String extraParam)
private void buildX(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, String configuredRegistry, List<String> platforms, File buildArchive, String extraParam)
throws MojoExecutionException {

BuildImageConfiguration buildConfiguration = imageConfig.getBuildConfiguration();
Expand All @@ -122,11 +122,11 @@ private void buildX(List<String> buildX, String builderName, BuildDirs buildDirs
cmdLine.add(String.join(",", platforms));
buildConfiguration.getTags().forEach(t -> {
cmdLine.add("--tag");
cmdLine.add(new ImageName(imageConfig.getName(), t).getFullName());
cmdLine.add(new ImageName(imageConfig.getName(), t).getFullName(configuredRegistry));
}
);
cmdLine.add("--tag");
cmdLine.add(imageConfig.getName());
cmdLine.add(new ImageName(imageConfig.getName()).getFullName(configuredRegistry));

Map<String, String> args = buildConfiguration.getArgs();
if (args != null) {
Expand Down Expand Up @@ -209,7 +209,7 @@ private String createBuilder(Path configPath, List<String> buildX, ImageConfigur
}

interface Builder<C> {
void useBuilder(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, C context) throws MojoExecutionException;
void useBuilder(List<String> buildX, String builderName, BuildDirs buildDirs, ImageConfiguration imageConfig, String configuredRegistry, C context) throws MojoExecutionException;
}

public interface Exec {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void pushImages(ProjectPaths projectPaths, Collection<ImageConfiguration>

AuthConfig authConfig = createAuthConfig(true, imageName.getUser(), configuredRegistry, registryConfig);
if (imageConfig.isBuildX()) {
buildXService.push(projectPaths, imageConfig, authConfig);
buildXService.push(projectPaths, imageConfig, configuredRegistry, authConfig);
} else {
dockerPush(retries, skipTag, buildConfig, name, configuredRegistry, authConfig);
}
Expand Down
115 changes: 102 additions & 13 deletions src/test/java/io/fabric8/maven/docker/service/RegistryServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Map;

/**
Expand All @@ -44,6 +45,8 @@
class RegistryServiceTest {

private Exception actualException;
private String registry;
private ImageConfiguration imageConfiguration;

// pull
private String imageName;
Expand All @@ -52,15 +55,11 @@ class RegistryServiceTest {
private AutoPullMode autoPullMode;
private RegistryService registryService;
private boolean hasImage;
private String registry;
private Map<String, String> authConfig;

@TempDir
private File projectBaseDir;

// push
private ImageConfiguration imageConfiguration;

@Mock
private DockerAccess docker;

Expand Down Expand Up @@ -95,6 +94,7 @@ void setup() {
autoPullMode = null;
hasImage = false;
registry = null;
imageConfiguration = null;
}

@ParameterizedTest
Expand Down Expand Up @@ -266,14 +266,52 @@ void pushImage() throws DockerAccessException {
thenNoExceptionThrown();
}

@Test
void pushImageWithRegistry() throws DockerAccessException {
String registry = "myregistry.com";
givenAnImageConfiguration("user/test:1.0.1");
givenRegistry(registry);

whenPushImage();

thenImageHasBeenPushed();
thenRegistryWasUsedWhenPushing(registry);
thenNoExceptionThrown();
}

@Test
void pushImageWithImageRegistry() throws DockerAccessException {
String registry = "myregistry.com";
givenAnImageConfiguration(registry + "/" + "user/test:1.0.1");

whenPushImage();

thenImageHasBeenPushed();
thenRegistryWasUsedWhenPushing(registry);
thenNoExceptionThrown();
}

@Test
void pushImageWithImageConfigRegistry() throws DockerAccessException {
String registry = "myregistry.com";
givenAnImageConfiguration("user/test:1.0.1");
andImageConfigRegistry(registry);

whenPushImage();

thenImageHasBeenPushed();
thenRegistryWasUsedWhenPushing(registry);
thenNoExceptionThrown();
}

@Test
void pushBuildXImage() throws MojoExecutionException {
givenBuildxImageConfiguration("user/test:1.0.1", null, null, null);
givenCredentials("skroob", "12345");

whenPushImage();

thenBuildxImageHasBeenPushed(null, null, false);
thenBuildxImageHasBeenPushed(null, null, false, null);
thenNoExceptionThrown();
}

Expand All @@ -285,7 +323,7 @@ void pushBuildXImageWithDockerfile() throws MojoExecutionException {

whenPushImage();

thenBuildxImageHasBeenPushed(null, "Dockerfile", false);
thenBuildxImageHasBeenPushed(null, "Dockerfile", false, null);
thenNoExceptionThrown();
}

Expand All @@ -296,7 +334,7 @@ void pushBuildXImageProvidedBuilder() throws MojoExecutionException {

whenPushImage();

thenBuildxImageHasBeenPushed("provided-builder", null, false);
thenBuildxImageHasBeenPushed("provided-builder", null, false, null);
thenNoExceptionThrown();
}

Expand All @@ -307,7 +345,45 @@ void pushBuildXImageTag() throws MojoExecutionException {

whenPushImage();

thenBuildxImageHasBeenPushed(null, null, true);
thenBuildxImageHasBeenPushed(null, null, true, null);
thenNoExceptionThrown();
}

@Test
void pushBuildXImageWithRegistry() throws MojoExecutionException {
String registry = "myregistry.com";
givenBuildxImageConfiguration("user/test:1.0.1", null, null, "perri-air");
givenCredentials("King_Roland_of_Druidia", "12345");
givenRegistry(registry);

whenPushImage();

thenBuildxImageHasBeenPushed(null, null, true, registry);
thenNoExceptionThrown();
}

@Test
void pushBuildXImageWithImageRegistry() throws MojoExecutionException {
String registry = "myregistry.com";
givenBuildxImageConfiguration(registry + "/" + "user/test:1.0.1", null, null, "perri-air");
givenCredentials("King_Roland_of_Druidia", "12345");

whenPushImage();

thenBuildxImageHasBeenPushed(null, null, true, registry);
thenNoExceptionThrown();
}

@Test
void pushBuildXImageWithImageConfigRegistry() throws MojoExecutionException {
String registry = "myregistry.com";
givenBuildxImageConfiguration("user/test:1.0.1", null, null, "perri-air");
andImageConfigRegistry(registry);
givenCredentials("King_Roland_of_Druidia", "12345");

whenPushImage();

thenBuildxImageHasBeenPushed(null, null, true, registry);
thenNoExceptionThrown();
}

Expand Down Expand Up @@ -349,9 +425,13 @@ private void thenImageHasNotBeenPushed() throws DockerAccessException {
private void thenImageHasBeenPushed() throws DockerAccessException {
Mockito.verify(docker).pushImage(Mockito.anyString(), Mockito.any(), Mockito.any(), Mockito.anyInt());
}
private void thenRegistryWasUsedWhenPushing(String registry) throws DockerAccessException {
Mockito.verify(docker).pushImage(Mockito.anyString(), Mockito.any(), Mockito.eq(registry), Mockito.anyInt());
}

private void thenBuildxImageHasBeenPushed(String providedBuilder, String relativeDockerfile, boolean tag, String registry) throws MojoExecutionException {

private void thenBuildxImageHasBeenPushed(String providedBuilder, String relativeDockerfile, boolean tag) throws MojoExecutionException {
Path buildPath = projectBaseDir.toPath().resolve("target/docker").resolve("user/test/1.0.1");
Path buildPath = projectBaseDir.toPath().resolve("target/docker").resolve(imageConfiguration.getName().replace(":","/"));
String config = getOsDependentBuild(buildPath, "docker");
String buildDir = getOsDependentBuild(buildPath, "build");
String builderName = providedBuilder != null ? providedBuilder : "maven";
Expand All @@ -367,9 +447,10 @@ private void thenBuildxImageHasBeenPushed(String providedBuilder, String relativ
"build", "--progress=plain", "--builder", builderName,
"--platform", "linux/amd64,linux/arm64"));
if (tag) {
args.addAll(Arrays.asList("--tag", "user/test:perri-air"));
String tagName = imageConfiguration.getBuildConfiguration().getTags().get(0);
args.addAll(Arrays.asList("--tag", new ImageName(imageConfiguration.getName(), tagName).getFullName(registry)));
}
args.addAll(Arrays.asList("--tag", "user/test:1.0.1", "--push"));
args.addAll(Arrays.asList("--tag", new ImageName(imageConfiguration.getName()).getFullName(registry) , "--push"));

String[] cmds;
if (relativeDockerfile != null) {
Expand Down Expand Up @@ -426,7 +507,9 @@ private void whenPushImage() {
RegistryService.RegistryConfig registryConfig =
new RegistryService.RegistryConfig.Builder()
.authConfigFactory(authConfigFactory)
.authConfig(authConfig).build();
.authConfig(authConfig)
.registry(registry)
.build();
registryService.pushImages(projectPaths, Collections.singleton(imageConfiguration), 1, registryConfig, false);
} catch (Exception e) {
this.actualException = e;
Expand Down Expand Up @@ -480,6 +563,12 @@ private void givenImageNameAndBuildX(String imageName, BuildXConfiguration build
imageConfiguration = new ImageConfiguration.Builder().name(imageName).buildConfig(buildImageConfiguration).build();
}

private void andImageConfigRegistry(String registry) {
Objects.requireNonNull(imageConfiguration, "ImageConfiguration must first be set with `givenAnImage....`");
imageConfiguration.setRegistry(registry);
}


private void givenCredentials(String username, String password) throws MojoExecutionException {
authConfig.put(AuthConfig.AUTH_USERNAME, username);
authConfig.put(AuthConfig.AUTH_PASSWORD, password);
Expand Down

0 comments on commit 01c0b85

Please sign in to comment.