1
1
import contextlib
2
+ import io
3
+ import tarfile
4
+ from pathlib import Path
2
5
from platform import system
3
6
from socket import socket
4
- from typing import TYPE_CHECKING , Optional
7
+ from typing import TYPE_CHECKING , Optional , Tuple
5
8
6
9
import docker .errors
7
10
from docker import version
@@ -52,6 +55,7 @@ def __init__(
52
55
self ._network : Optional [Network ] = None
53
56
self ._network_aliases : Optional [list [str ]] = None
54
57
self ._kwargs = kwargs
58
+ self ._files : list [Tuple [Path , Path ]] = []
55
59
56
60
def with_env (self , key : str , value : str ) -> Self :
57
61
self .env [key ] = value
@@ -78,6 +82,33 @@ def with_kwargs(self, **kwargs) -> Self:
78
82
self ._kwargs = kwargs
79
83
return self
80
84
85
+ def with_copy_file_to_container (self , source_file : Path , destination_file : Path ) -> Self :
86
+ self ._files .append ((source_file , destination_file ))
87
+
88
+ return self
89
+
90
+ def copy_file_from_container (self , container_file : str , destination_file : str ) -> str :
91
+ tar_stream , _ = self ._container .get_archive (container_file )
92
+
93
+ for chunk in tar_stream :
94
+ with tarfile .open (fileobj = io .BytesIO (chunk )) as tar :
95
+ for member in tar .getmembers ():
96
+ with open (destination_file , 'wb' ) as f :
97
+ f .write (tar .extractfile (member ).read ())
98
+
99
+ return destination_file
100
+
101
+ @staticmethod
102
+ def _put_file_in_container (container , source_file : Path , destination_file : str ):
103
+ data = io .BytesIO ()
104
+
105
+ with tarfile .open (fileobj = data , mode = 'w' ) as tar :
106
+ tar .add (source_file , arcname = destination_file )
107
+
108
+ data .seek (0 )
109
+
110
+ container .put_archive ("/" , data )
111
+
81
112
def maybe_emulate_amd64 (self ) -> Self :
82
113
if is_arm ():
83
114
return self .with_kwargs (platform = "linux/amd64" )
@@ -115,6 +146,14 @@ def start(self) -> Self:
115
146
)
116
147
117
148
logger .info ("Container started: %s" , self ._container .short_id )
149
+ if self ._network :
150
+ self ._network .connect (self ._container .id , self ._network_aliases )
151
+
152
+ for file in self ._files :
153
+ source , destination = file [0 ], file [1 ]
154
+
155
+ DockerContainer ._put_file_in_container (self ._container , source , destination )
156
+
118
157
return self
119
158
120
159
def stop (self , force = True , delete_volume = True ) -> None :
0 commit comments