Skip to content

Commit 2af42e8

Browse files
committed
add copying files to/from container
Signed-off-by: mgorsk1 <[email protected]>
1 parent 1e43923 commit 2af42e8

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

core/testcontainers/core/container.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import contextlib
2+
import io
3+
import tarfile
4+
from pathlib import Path
25
from platform import system
36
from socket import socket
4-
from typing import TYPE_CHECKING, Optional
7+
from typing import TYPE_CHECKING, Optional, Tuple
58

69
import docker.errors
710
from typing_extensions import Self
@@ -50,6 +53,7 @@ def __init__(
5053
self._network: Optional[Network] = None
5154
self._network_aliases: Optional[list[str]] = None
5255
self._kwargs = kwargs
56+
self._files: list[Tuple[Path, Path]] = []
5357

5458
def with_env(self, key: str, value: str) -> Self:
5559
self.env[key] = value
@@ -76,6 +80,33 @@ def with_kwargs(self, **kwargs) -> Self:
7680
self._kwargs = kwargs
7781
return self
7882

83+
def with_copy_file_to_container(self, source_file: Path, destination_file: Path) -> Self:
84+
self._files.append((source_file, destination_file))
85+
86+
return self
87+
88+
def copy_file_from_container(self, container_file: str, destination_file: str) -> str:
89+
tar_stream, _ = self._container.get_archive(container_file)
90+
91+
for chunk in tar_stream:
92+
with tarfile.open(fileobj=io.BytesIO(chunk)) as tar:
93+
for member in tar.getmembers():
94+
with open(destination_file, 'wb') as f:
95+
f.write(tar.extractfile(member).read())
96+
97+
return destination_file
98+
99+
@staticmethod
100+
def _put_file_in_container(container, source_file: Path, destination_file: str):
101+
data = io.BytesIO()
102+
103+
with tarfile.open(fileobj=data, mode='w') as tar:
104+
tar.add(source_file, arcname=destination_file)
105+
106+
data.seek(0)
107+
108+
container.put_archive("/", data)
109+
79110
def maybe_emulate_amd64(self) -> Self:
80111
if is_arm():
81112
return self.with_kwargs(platform="linux/amd64")
@@ -88,7 +119,7 @@ def start(self) -> Self:
88119
logger.info("Pulling image %s", self.image)
89120
docker_client = self.get_docker_client()
90121
self._configure()
91-
self._container = docker_client.run(
122+
self._container: Container = docker_client.run(
92123
self.image,
93124
command=self._command,
94125
detach=True,
@@ -101,6 +132,12 @@ def start(self) -> Self:
101132
logger.info("Container started: %s", self._container.short_id)
102133
if self._network:
103134
self._network.connect(self._container.id, self._network_aliases)
135+
136+
for file in self._files:
137+
source, destination = file[0], file[1]
138+
139+
DockerContainer._put_file_in_container(self._container, source, destination)
140+
104141
return self
105142

106143
def stop(self, force=True, delete_volume=True) -> None:

0 commit comments

Comments
 (0)