Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the streaming of the docker.compose.pull logs #497

Merged
merged 1 commit into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 39 additions & 2 deletions python_on_whales/components/compose/cli_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,13 +434,36 @@ def ls(
for proj in json.loads(run(full_cmd))
]

@overload
def pull(
self,
services: Union[List[str], str, None] = ...,
ignore_pull_failures: bool = ...,
include_deps: bool = ...,
quiet: bool = ...,
stream_logs: Literal[True] = ...,
) -> Iterable[Tuple[str, bytes]]:
...

@overload
def pull(
self,
services: Union[List[str], str, None] = ...,
ignore_pull_failures: bool = ...,
include_deps: bool = ...,
quiet: bool = ...,
stream_logs: Literal[False] = ...,
) -> None:
...

def pull(
self,
services: Union[List[str], str, None] = None,
ignore_pull_failures: bool = False,
include_deps: bool = False,
quiet: bool = False,
):
stream_logs: bool = False,
) -> Union[Iterable[Tuple[str, bytes]], None]:
"""Pull service images
Parameters:
Expand All @@ -452,8 +475,19 @@ def pull(
include_deps: Also pull services declared as dependencies
quiet: By default, the progress bars are printed in stdout and stderr (both).
To disable all output, use `quiet=True`
stream_logs: If `False` this function returns None. If `True`, this
function returns an Iterable of `Tuple[str, bytes]` where the first element
is the type of log (`"stdin"` or `"stdout"`). The second element is the log itself,
as bytes, you'll need to call `.decode()` if you want the logs as `str`.
See [the streaming guide](https://gabrieldemarmiesse.github.io/python-on-whales/user_guide/docker_run/#stream-the-output) if you are
not familiar with the streaming of logs in Python-on-whales.
"""
if quiet and stream_logs:
raise ValueError(
"It's not possible to have stream_logs=True and quiet=True at the same time. "
"Only one can be activated at a time."
)
full_cmd = self.docker_compose_cmd + ["pull"]
full_cmd.add_flag("--ignore-pull-failures", ignore_pull_failures)
full_cmd.add_flag("--include-deps", include_deps)
Expand All @@ -463,7 +497,10 @@ def pull(
elif services is not None:
services = to_list(services)
full_cmd += services
run(full_cmd, capture_stdout=False, capture_stderr=False)
if stream_logs:
return stream_stdout_and_stderr(full_cmd)
else:
run(full_cmd, capture_stdout=False, capture_stderr=False)

def push(self, services: Optional[List[str]] = None):
"""Push service images
Expand Down
15 changes: 15 additions & 0 deletions tests/python_on_whales/components/test_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,21 @@ def test_docker_compose_pull():
docker.compose.pull(["busybox", "alpine"], quiet=True)


def test_docker_compose_pull_stream():
try:
docker.image.remove("busybox")
except NoSuchImage:
pass
logs = list(docker.compose.pull("busybox", stream_logs=True))
assert len(logs) >= 3
logs_as_big_binary = b""
for log_type, log_value in logs:
assert log_type in ("stdout", "stderr")
logs_as_big_binary += log_value
assert b"busybox Pulled" in logs_as_big_binary
assert b"Pull complete" in logs_as_big_binary


def test_docker_compose_pull_ignore_pull_failures():
docker = DockerClient(
compose_files=[
Expand Down