Skip to content

Commit

Permalink
fix: allow pushing images with different arch/os to docker daemon
Browse files Browse the repository at this point in the history
  • Loading branch information
mpeddada1 committed Jun 6, 2024
1 parent b06b001 commit 982897e
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,9 @@ public void testBasicMultiPlatform_toDockerDaemon()
}

@Test
public void testBasicMultiPlatform_toDockerDaemon_noMatchingImage() {
ExecutionException exception =
assertThrows(
ExecutionException.class,
() ->
Jib.from(
RegistryImage.named(
public void testBasicMultiPlatform_toDockerDaemon_pickFirstPlatformWhenNoMatchingImage() throws IOException, InterruptedException, InvalidImageReferenceException, CacheDirectoryCreationException, ExecutionException, RegistryException {
Jib.from(
RegistryImage.named(
"busybox@sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977"))
.setPlatforms(
ImmutableSet.of(
Expand All @@ -359,11 +355,15 @@ public void testBasicMultiPlatform_toDockerDaemon_noMatchingImage() {
Containerizer.to(
DockerDaemonImage.named(
dockerHost + ":5000/docker-daemon-multi-platform"))
.setAllowInsecureRegistries(true)));
assertThat(exception)
.hasCauseThat()
.hasMessageThat()
.startsWith("The configured platforms don't match the Docker Engine's OS and architecture");
.setAllowInsecureRegistries(true));
String os =
new Command("docker", "inspect", dockerHost + ":5000/docker-daemon-multi-platform", "--format", "{{.Os}}")
.run().replace("\n", "");
String architecture =
new Command("docker", "inspect", dockerHost + ":5000/docker-daemon-multi-platform", "--format", "{{.Architecture}}")
.run().replace("\n", "");
assertThat(os).isEqualTo("linux");
assertThat(architecture).isEqualTo("s390x");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,14 +624,9 @@ private void loadDocker(
DockerInfoDetails dockerInfoDetails = dockerClient.info();
String osType = dockerInfoDetails.getOsType();
String architecture = normalizeArchitecture(dockerInfoDetails.getArchitecture());
Optional<Image> builtImage = fetchBuiltImageForLocalBuild(osType, architecture);
Preconditions.checkState(
builtImage.isPresent(),
String.format(
"The configured platforms don't match the Docker Engine's OS and architecture (%s/%s)",
osType, architecture));
Image builtImage = fetchBuiltImageForLocalBuild(osType, architecture);
return new LoadDockerStep(
buildContext, progressDispatcherFactory, dockerClient, builtImage.get())
buildContext, progressDispatcherFactory, dockerClient, builtImage)
.call();
});
}
Expand Down Expand Up @@ -669,21 +664,22 @@ String normalizeArchitecture(String architecture) {
}

@VisibleForTesting
Optional<Image> fetchBuiltImageForLocalBuild(String osType, String architecture)
Image fetchBuiltImageForLocalBuild(String osType, String architecture)
throws InterruptedException, ExecutionException {
if (results.baseImagesAndBuiltImages.get().size() > 1) {
LOGGER.warning(
String.format(
"Detected multi-platform configuration, only building the one that matches the local Docker Engine's os and architecture (%s/%s)",
"Detected multi-platform configuration, only building the one that matches the local Docker Engine's os and architecture (%s/%s) or " +
"the first platform specified",
osType, architecture));
}
for (Map.Entry<Image, Future<Image>> imageEntry :
results.baseImagesAndBuiltImages.get().entrySet()) {
Image image = imageEntry.getValue().get();
if (image.getArchitecture().equals(architecture) && image.getOs().equals(osType)) {
return Optional.of(image);
for (Map.Entry<Image, Future<Image>> imageEntry :
results.baseImagesAndBuiltImages.get().entrySet()) {
Image image = imageEntry.getValue().get();
if (image.getArchitecture().equals(architecture) && image.getOs().equals(osType)) {
return image;
}
}
}
return Optional.empty();
return results.baseImagesAndBuiltImages.get().values().iterator().next().get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,14 @@ public void testFetchBuildImageForLocalBuild_matchingOsAndArch()
Futures.immediateFuture(builtAmd64AndWindowsImage))));
stepsRunner.buildImages(progressDispatcherFactory);

Optional<Image> expectedImage = stepsRunner.fetchBuiltImageForLocalBuild("windows", "amd64");
Image expectedImage = stepsRunner.fetchBuiltImageForLocalBuild("windows", "amd64");

assertThat(expectedImage.get().getOs()).isEqualTo("windows");
assertThat(expectedImage.get().getArchitecture()).isEqualTo("amd64");
assertThat(expectedImage.getOs()).isEqualTo("windows");
assertThat(expectedImage.getArchitecture()).isEqualTo("amd64");
}

@Test
public void testFetchBuildImageForLocalBuild_differentOs()
public void testFetchBuildImageForLocalBuild_differentOs_buildImageForFirstPlatform()
throws ExecutionException, InterruptedException {
when(builtArm64AndLinuxImage.getArchitecture()).thenReturn("arm64");
when(builtArm64AndLinuxImage.getOs()).thenReturn("linux");
Expand All @@ -225,13 +225,15 @@ public void testFetchBuildImageForLocalBuild_differentOs()
Futures.immediateFuture(builtAmd64AndWindowsImage))));
stepsRunner.buildImages(progressDispatcherFactory);

Optional<Image> expectedImage = stepsRunner.fetchBuiltImageForLocalBuild("os", "arm64");
Image expectedImage = stepsRunner.fetchBuiltImageForLocalBuild("os", "arm64");

assertThat(expectedImage.getOs()).isEqualTo("linux");
assertThat(expectedImage.getArchitecture()).isEqualTo("arm64");

assertThat(expectedImage.isPresent()).isFalse();
}

@Test
public void testFetchBuildImageForLocalBuild_differentArch()
public void testFetchBuildImageForLocalBuild_differentArch_buildImageForFirstPlatform()
throws ExecutionException, InterruptedException {
when(builtArm64AndLinuxImage.getArchitecture()).thenReturn("arm64");
when(builtAmd64AndWindowsImage.getArchitecture()).thenReturn("amd64");
Expand All @@ -245,9 +247,30 @@ public void testFetchBuildImageForLocalBuild_differentArch()
Futures.immediateFuture(builtAmd64AndWindowsImage))));
stepsRunner.buildImages(progressDispatcherFactory);

Optional<Image> expectedImage = stepsRunner.fetchBuiltImageForLocalBuild("linux", "arch");
Image expectedImage = stepsRunner.fetchBuiltImageForLocalBuild("linux", "arch");

assertThat(expectedImage.getArchitecture()).isEqualTo("arm64");
}

@Test
public void testFetchBuildImageForLocalBuild_singleImage_imagePlatformDifferentFromDockerEnv()
throws ExecutionException, InterruptedException {
when(builtArm64AndLinuxImage.getArchitecture()).thenReturn("arm64");
when(builtArm64AndLinuxImage.getOs()).thenReturn("linux");

when(builtAmd64AndWindowsImage.getOs()).thenReturn("linux");
when(executorService.submit(Mockito.any(Callable.class)))
.thenReturn(
Futures.immediateFuture(
ImmutableMap.of(
baseImage1,
Futures.immediateFuture(builtArm64AndLinuxImage))));
stepsRunner.buildImages(progressDispatcherFactory);

Image expectedImage = stepsRunner.fetchBuiltImageForLocalBuild("linux", "amd64");

assertThat(expectedImage.isPresent()).isFalse();
assertThat(expectedImage.getOs()).isEqualTo("linux");
assertThat(expectedImage.getArchitecture()).isEqualTo("arm64");
}

@Test
Expand Down

0 comments on commit 982897e

Please sign in to comment.