diff --git a/python_on_whales/components/image/cli_wrapper.py b/python_on_whales/components/image/cli_wrapper.py index a831b886..9a5c1bd5 100644 --- a/python_on_whales/components/image/cli_wrapper.py +++ b/python_on_whales/components/image/cli_wrapper.py @@ -476,7 +476,10 @@ def prune(self, all: bool = False, filter: Dict[str, str] = {}) -> str: return run(full_cmd) def pull( - self, x: Union[str, List[str]], quiet: bool = False + self, + x: Union[str, List[str]], + quiet: bool = False, + platform: Optional[str] = None, ) -> Union[Image, List[Image]]: """Pull one or more docker image(s) @@ -488,6 +491,7 @@ def pull( The progress bars might look strange as multiple processes are drawing on the terminal at the same time. quiet: If you don't want to see the progress bars. + platform: If you want to enforce a platform. Returns: The Docker image loaded (`python_on_whales.Image` object). @@ -498,23 +502,28 @@ def pull( if x == []: return [] elif isinstance(x, str): - return self._pull_single_tag(x, quiet=quiet) + return self._pull_single_tag(x, quiet=quiet, platform=platform) elif isinstance(x, list) and len(x) == 1: - return [self._pull_single_tag(x[0], quiet=quiet)] + return [self._pull_single_tag(x[0], quiet=quiet, platform=platform)] elif len(x) >= 2: pool = ThreadPool(4) - generator = self._generate_args_push_pull(x, quiet) + generator = self._generate_args_pull(x, quiet, platform) all_images = pool.starmap(self._pull_single_tag, generator) pool.close() pool.join() return all_images - def _pull_single_tag(self, image_name: str, quiet: bool): + def _pull_single_tag( + self, image_name: str, quiet: bool, platform: Optional[str] = None + ): full_cmd = self.docker_cmd + ["image", "pull"] if quiet: full_cmd.append("--quiet") + if platform: + full_cmd.append(f"--platform={platform}") + full_cmd.append(image_name) run(full_cmd, capture_stdout=quiet, capture_stderr=quiet) return Image(self.client_config, image_name) @@ -545,18 +554,27 @@ def push(self, x: Union[str, List[str]], quiet: bool = False): self._push_single_tag(x[0], quiet=quiet) elif len(x) >= 2: pool = ThreadPool(4) - generator = self._generate_args_push_pull(x, quiet) + generator = self._generate_args_push(x, quiet) pool.starmap(self._push_single_tag, generator) pool.close() pool.join() - def _generate_args_push_pull(self, _list: List[str], quiet: bool): + def _generate_args_pull( + self, _list: List[str], quiet: bool, platform: Optional[str] = None + ): + for tag in _list: + yield tag, quiet, platform + + def _generate_args_push(self, _list: List[str], quiet: bool): for tag in _list: yield tag, quiet def _push_single_tag(self, tag_or_repo: str, quiet: bool): full_cmd = self.docker_cmd + ["image", "push"] + if quiet: + full_cmd.append("--quiet") + full_cmd.append(tag_or_repo) run(full_cmd, capture_stdout=quiet, capture_stderr=quiet) diff --git a/tests/python_on_whales/components/test_manifest.py b/tests/python_on_whales/components/test_manifest.py index 74a8268e..f168c98e 100644 --- a/tests/python_on_whales/components/test_manifest.py +++ b/tests/python_on_whales/components/test_manifest.py @@ -24,13 +24,13 @@ def with_manifest(): @pytest.fixture def with_platform_variant_manifest(request): - image_with_platform_variant = "arm64v8/busybox:1.35" + image_with_platform_variant = "arm32v7/busybox:1.35" def remove_docker_image(): docker.image.remove(image_with_platform_variant) request.addfinalizer(remove_docker_image) - docker.image.pull(image_with_platform_variant, quiet=True) + docker.image.pull(image_with_platform_variant, quiet=True, platform="linux/arm/v7") return docker.image.inspect(image_with_platform_variant) @@ -63,5 +63,5 @@ def test_manifest_annotate(with_manifest): def test_manifest_platform_variant(with_platform_variant_manifest): assert "linux" in repr(with_platform_variant_manifest.os) - assert "arm64" in repr(with_platform_variant_manifest.architecture) - assert "v8" in repr(with_platform_variant_manifest.variant) + assert "arm" in repr(with_platform_variant_manifest.architecture) + assert "v7" in repr(with_platform_variant_manifest.variant)