Skip to content

Commit b273d31

Browse files
Add timeout kwarg to exec (#673)
1 parent 4ccb1fa commit b273d31

File tree

4 files changed

+24
-1
lines changed

4 files changed

+24
-1
lines changed

kr8s/_exec.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def __init__(
3535
stderr: BinaryIO | None = None,
3636
check: bool = True,
3737
capture_output: bool = True,
38+
timeout: int | None = None,
3839
) -> None:
3940
self._resource = resource
4041
self._container = container
@@ -43,6 +44,7 @@ def __init__(
4344
self._stdout = stdout
4445
self._stderr = stderr
4546
self._capture_output = capture_output
47+
self._timeout = timeout
4648

4749
self.args = command
4850
self.stdout = b""
@@ -80,7 +82,7 @@ async def run(
8082
await ws.send_bytes(STDIN_CHANNEL.to_bytes() + self._stdin.read()) # type: ignore
8183
await ws.send_bytes(CLOSE_CHANNEL.to_bytes() + STDIN_CHANNEL.to_bytes()) # type: ignore
8284
while True:
83-
message = await ws.receive_bytes()
85+
message = await ws.receive_bytes(timeout=self._timeout)
8486
channel, message = int(message[0]), message[1:]
8587
if message:
8688
if channel == STDOUT_CHANNEL:

kr8s/_objects.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ async def exec(
506506
stderr: BinaryIO | None = None,
507507
check: bool = True,
508508
capture_output: bool = True,
509+
timeout: int | None = None,
509510
) -> CompletedExec:
510511
"""Execute a command in this object."""
511512
return await self.async_exec(
@@ -516,6 +517,7 @@ async def exec(
516517
stderr=stderr,
517518
check=check,
518519
capture_output=capture_output,
520+
timeout=timeout,
519521
)
520522

521523
async def async_exec(
@@ -528,6 +530,7 @@ async def async_exec(
528530
stderr: BinaryIO | None = None,
529531
check: bool = True,
530532
capture_output: bool = True,
533+
timeout: int | None = None,
531534
) -> CompletedExec:
532535
"""Execute a command in this object."""
533536
if not hasattr(self, "ready_pods"):
@@ -544,6 +547,7 @@ async def async_exec(
544547
stderr=stderr,
545548
check=check,
546549
capture_output=capture_output,
550+
timeout=timeout,
547551
)
548552

549553
async def async_watch(self) -> AsyncGenerator[tuple[str, Self]]:
@@ -1393,6 +1397,7 @@ async def async_exec(
13931397
stderr: BinaryIO | None = None,
13941398
check: bool = True,
13951399
capture_output: bool = True,
1400+
timeout: int | None = None,
13961401
) -> CompletedExec:
13971402
while not await self.async_ready():
13981403
await anyio.sleep(0.1)
@@ -1406,6 +1411,7 @@ async def async_exec(
14061411
stdin=stdin,
14071412
check=check,
14081413
capture_output=capture_output,
1414+
timeout=timeout,
14091415
)
14101416
async with ex.run() as process:
14111417
await process.wait()
@@ -1421,6 +1427,7 @@ async def exec(
14211427
stderr: BinaryIO | None = None,
14221428
check: bool = True,
14231429
capture_output: bool = True,
1430+
timeout: int | None = None,
14241431
) -> CompletedExec:
14251432
"""Run a command in a container and wait until it completes.
14261433
@@ -1441,6 +1448,8 @@ async def exec(
14411448
If True, raise an exception if the command fails.
14421449
capture_output:
14431450
If True, store stdout and stderr from the container in an attribute.
1451+
timeout:
1452+
If set, timeout for recieving bytes.
14441453
14451454
Returns:
14461455
A :class:`kr8s._exec.CompletedExec` object.
@@ -1460,6 +1469,7 @@ async def exec(
14601469
stderr=stderr,
14611470
check=check,
14621471
capture_output=capture_output,
1472+
timeout=timeout,
14631473
)
14641474

14651475
@classmethod

kr8s/objects.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ def exec( # type: ignore[override]
241241
stderr: BinaryIO | None = None,
242242
check: bool = True,
243243
capture_output: bool = True,
244+
timeout: int | None = None,
244245
) -> CompletedExec:
245246
return as_sync_func(self.async_exec)(
246247
command,
@@ -250,6 +251,7 @@ def exec( # type: ignore[override]
250251
stderr=stderr,
251252
check=check,
252253
capture_output=capture_output,
254+
timeout=timeout,
253255
)
254256

255257
def tolerate( # type: ignore[override]

kr8s/tests/test_objects.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,15 @@ async def test_pod_exec(ubuntu_pod):
11101110
assert ex.returncode == 0
11111111

11121112

1113+
async def test_pod_exec_timeout(ubuntu_pod):
1114+
ex = await ubuntu_pod.exec(["date"], timeout=2)
1115+
assert isinstance(ex, CompletedExec)
1116+
assert str(datetime.datetime.now().year) in ex.stdout.decode()
1117+
assert ex.args == ["date"]
1118+
assert ex.stderr == b""
1119+
assert ex.returncode == 0
1120+
1121+
11131122
async def test_pod_exec_error(ubuntu_pod):
11141123
with pytest.raises(ExecError):
11151124
await ubuntu_pod.exec(["date", "foo"])

0 commit comments

Comments
 (0)