18
18
19
19
import com .google .cloud .tools .jib .api .DescriptorDigest ;
20
20
import com .google .cloud .tools .jib .api .DockerClient ;
21
+ import com .google .cloud .tools .jib .api .DockerInfoDetails ;
21
22
import com .google .cloud .tools .jib .blob .BlobDescriptor ;
22
23
import com .google .cloud .tools .jib .builder .ProgressEventDispatcher ;
23
24
import com .google .cloud .tools .jib .builder .steps .LocalBaseImageSteps .LocalImage ;
52
53
import java .util .concurrent .ExecutorService ;
53
54
import java .util .concurrent .Future ;
54
55
import java .util .function .Consumer ;
56
+ import java .util .logging .Logger ;
55
57
import java .util .stream .Collectors ;
56
58
import javax .annotation .Nullable ;
57
59
64
66
*/
65
67
public class StepsRunner {
66
68
69
+ private static final Logger LOGGER = Logger .getLogger (StepsRunner .class .getName ());
70
+
67
71
/** Holds the individual step results. */
68
72
private static class StepResults {
69
73
@@ -413,7 +417,8 @@ private void buildAndCacheApplicationLayers(
413
417
BuildAndCacheApplicationLayerStep .makeList (buildContext , progressDispatcherFactory ));
414
418
}
415
419
416
- private void buildImages (ProgressEventDispatcher .Factory progressDispatcherFactory ) {
420
+ @ VisibleForTesting
421
+ void buildImages (ProgressEventDispatcher .Factory progressDispatcherFactory ) {
417
422
results .baseImagesAndBuiltImages =
418
423
executorService .submit (
419
424
() -> {
@@ -616,13 +621,17 @@ private void loadDocker(
616
621
results .buildResult =
617
622
executorService .submit (
618
623
() -> {
619
- Verify .verify (
620
- results .baseImagesAndBuiltImages .get ().size () == 1 ,
621
- "multi-platform image building not supported when pushing to Docker engine" );
622
- Image builtImage =
623
- results .baseImagesAndBuiltImages .get ().values ().iterator ().next ().get ();
624
+ DockerInfoDetails dockerInfoDetails = dockerClient .info ();
625
+ String osType = dockerInfoDetails .getOsType ();
626
+ String architecture = normalizeArchitecture (dockerInfoDetails .getArchitecture ());
627
+ Optional <Image > builtImage = fetchBuiltImageForLocalBuild (osType , architecture );
628
+ Preconditions .checkState (
629
+ builtImage .isPresent (),
630
+ String .format (
631
+ "The configured platforms don't match the Docker Engine's OS and architecture (%s/%s)" ,
632
+ osType , architecture ));
624
633
return new LoadDockerStep (
625
- buildContext , progressDispatcherFactory , dockerClient , builtImage )
634
+ buildContext , progressDispatcherFactory , dockerClient , builtImage . get () )
626
635
.call ();
627
636
});
628
637
}
@@ -647,4 +656,34 @@ private void writeTarFile(
647
656
private <E > List <Future <E >> scheduleCallables (ImmutableList <? extends Callable <E >> callables ) {
648
657
return callables .stream ().map (executorService ::submit ).collect (Collectors .toList ());
649
658
}
659
+
660
+ @ VisibleForTesting
661
+ String normalizeArchitecture (String architecture ) {
662
+ // Create mapping based on https://docs.docker.com/engine/install/#supported-platforms
663
+ if (architecture .equals ("x86_64" )) {
664
+ return "amd64" ;
665
+ } else if (architecture .equals ("aarch64" )) {
666
+ return "arm64" ;
667
+ }
668
+ return architecture ;
669
+ }
670
+
671
+ @ VisibleForTesting
672
+ Optional <Image > fetchBuiltImageForLocalBuild (String osType , String architecture )
673
+ throws InterruptedException , ExecutionException {
674
+ if (results .baseImagesAndBuiltImages .get ().size () > 1 ) {
675
+ LOGGER .warning (
676
+ String .format (
677
+ "Detected multi-platform configuration, only building the one that matches the local Docker Engine's os and architecture (%s/%s)" ,
678
+ osType , architecture ));
679
+ }
680
+ for (Map .Entry <Image , Future <Image >> imageEntry :
681
+ results .baseImagesAndBuiltImages .get ().entrySet ()) {
682
+ Image image = imageEntry .getValue ().get ();
683
+ if (image .getArchitecture ().equals (architecture ) && image .getOs ().equals (osType )) {
684
+ return Optional .of (image );
685
+ }
686
+ }
687
+ return Optional .empty ();
688
+ }
650
689
}
0 commit comments