Skip to content

Commit

Permalink
Implemented "attach" command. (#371)
Browse files Browse the repository at this point in the history
  • Loading branch information
MisterOwlPT authored Oct 28, 2022
1 parent cf24a36 commit f849a1a
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ Use the right tool for the right job 🙂
| buildx | 10/11 | ![92%](https://progress-bar.dev/92) |
| compose | 18/23 | ![73%](https://progress-bar.dev/78) |
| config | 4/4 | ![50%](https://progress-bar.dev/100) |
| container | 22/24 | ![50%](https://progress-bar.dev/91) |
| container | 23/24 | ![50%](https://progress-bar.dev/91) |
| context | 4/6 | ![50%](https://progress-bar.dev/67) |
| image | 12/13 | ![50%](https://progress-bar.dev/92) |
| manifest | 0/4 | ![50%](https://progress-bar.dev/0) |
Expand Down
1 change: 1 addition & 0 deletions docs/template/docker_client.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

They're actually aliases

* [`docker.attach`](sub-commands/container.md#attach)
* [`docker.build`](sub-commands/buildx.md#build)
* [`docker.commit`](sub-commands/container.md#commit)
* [`docker.copy`](sub-commands/container.md#copy)
Expand Down
47 changes: 44 additions & 3 deletions python_on_whales/components/container/cli_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,21 @@ def __repr__(self):
# --------------------------------------------------------------------
# public methods

def attach(
self,
detach_keys: Optional[str] = None,
stdin: bool = True,
sig_proxy: bool = True,
) -> None:
"""Attach local standard input, output, and error streams to a running container.
Alias: `docker.attach(...)`
See the [`docker.container.attach`](../sub-commands/container.md#attach) command for
information about the arguments.
"""
ContainerCLI(self.client_config).attach(self, detach_keys, not stdin, sig_proxy)

def commit(
self,
tag: Optional[str] = None,
Expand Down Expand Up @@ -353,9 +368,35 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.remove = self.remove

def attach(self):
"""Not yet implemented"""
raise NotImplementedError
def attach(
self,
container: ValidContainer,
detach_keys: Optional[str] = None,
stdin: bool = True,
sig_proxy: bool = True,
) -> None:
"""Attach local standard input, output, and error streams to a running container
Alias: `docker.attach(...)`
# Arguments
container: The running container to attach to
detach_keys: Override the key sequence for detaching a container
stdin: Attach STDIN
sig_proxy: Proxy all received signals to the process (default true)
# Raises
`python_on_whales.exceptions.NoSuchContainer` if the container does not exists.
"""
self.inspect(container)

full_cmd = self.docker_cmd + ["attach"]
full_cmd.add_simple_arg("--detach-keys", detach_keys)
full_cmd.add_flag("--no-stdin", not stdin)
full_cmd.add_flag("--sig-proxy", sig_proxy)
full_cmd.append(container)

run(full_cmd, tty=True)

def commit(
self,
Expand Down
2 changes: 1 addition & 1 deletion python_on_whales/docker_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def __init__(
self.volume = VolumeCLI(self.client_config)

# aliases
self.attach = None
self.attach = self.container.attach
self.build = self.buildx.build
self.legacy_build = self.image.legacy_build
self.commit = self.container.commit
Expand Down
79 changes: 75 additions & 4 deletions tests/python_on_whales/components/test_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import time
from datetime import datetime, timedelta, timezone
from pathlib import Path
from unittest.mock import Mock, patch

import pytest

Expand Down Expand Up @@ -560,16 +561,17 @@ def test_exec_change_directory():
@pytest.mark.parametrize(
"docker_function",
[
docker.container.remove,
docker.container.stop,
docker.container.attach,
docker.container.commit,
docker.container.diff,
docker.container.inspect,
docker.container.kill,
docker.container.logs,
docker.container.pause,
docker.container.remove,
docker.container.restart,
docker.container.start,
docker.container.commit,
docker.container.logs,
docker.container.stop,
docker.container.unpause,
docker.container.wait,
],
Expand Down Expand Up @@ -631,3 +633,72 @@ def test_prune():
def test_run_detached_interactive():
with docker.run("ubuntu", interactive=True, detach=True, tty=False) as c:
c.execute(["true"])


@patch("python_on_whales.components.container.cli_wrapper.ContainerCLI.inspect")
@patch("python_on_whales.components.container.cli_wrapper.run")
def test_attach_default(run_mock: Mock, inspect_mock: Mock) -> None:

test_container_name = "test_dummy_container"

docker.attach(test_container_name)

inspect_mock.assert_called_once_with(test_container_name)
run_mock.assert_called_once_with(
docker.client_config.docker_cmd
+ ["attach", "--sig-proxy", test_container_name],
tty=True,
)


@patch("python_on_whales.components.container.cli_wrapper.ContainerCLI.inspect")
@patch("python_on_whales.components.container.cli_wrapper.run")
def test_attach_detach_keys_argument(run_mock: Mock, inspect_mock: Mock) -> None:

test_container_name = "test_dummy_container"
test_detach_key = "dummy"

docker.attach(test_container_name, detach_keys=test_detach_key)

inspect_mock.assert_called_once_with(test_container_name)
run_mock.assert_called_once_with(
docker.client_config.docker_cmd
+ [
"attach",
"--detach-keys",
test_detach_key,
"--sig-proxy",
test_container_name,
],
tty=True,
)


@patch("python_on_whales.components.container.cli_wrapper.ContainerCLI.inspect")
@patch("python_on_whales.components.container.cli_wrapper.run")
def test_attach_no_stdin_argument(run_mock: Mock, inspect_mock: Mock) -> None:

test_container_name = "test_dummy_container"

docker.attach(test_container_name, stdin=False)

inspect_mock.assert_called_once_with(test_container_name)
run_mock.assert_called_once_with(
docker.client_config.docker_cmd
+ ["attach", "--no-stdin", "--sig-proxy", test_container_name],
tty=True,
)


@patch("python_on_whales.components.container.cli_wrapper.ContainerCLI.inspect")
@patch("python_on_whales.components.container.cli_wrapper.run")
def test_attach_sig_proxy_argument(run_mock: Mock, inspect_mock: Mock) -> None:

test_container_name = "test_dummy_container"

docker.attach(test_container_name, sig_proxy=False)

inspect_mock.assert_called_once_with(test_container_name)
run_mock.assert_called_once_with(
docker.client_config.docker_cmd + ["attach", test_container_name], tty=True
)

0 comments on commit f849a1a

Please sign in to comment.