10
10
import threading
11
11
import time
12
12
from functools import wraps
13
- from typing import Any , Dict , Iterable , List , Optional , Set , Union
13
+ from typing import Any , Callable , Dict , Iterable , List , Optional , Set , Union
14
14
15
15
from localstack import config , constants
16
16
from localstack .config import HostAndPort , default_ip , is_env_true
38
38
from localstack .utils .serving import Server
39
39
from localstack .utils .strings import short_uid
40
40
from localstack .utils .sync import poll_condition
41
- from localstack .utils .tail import FileListener
42
41
43
42
LOG = logging .getLogger (__name__ )
44
43
@@ -907,8 +906,47 @@ def stopped(self) -> Container:
907
906
return Container (container_config = self .config , docker_client = self .container_client )
908
907
909
908
909
+ class ContainerLogPrinter :
910
+ """
911
+ Waits on a container to start and then uses ``stream_logs`` to print each line of the logs.
912
+ """
913
+
914
+ def __init__ (self , container : Container , callback : Callable [[str ], None ] = print ):
915
+ self .container = container
916
+ self .callback = callback
917
+
918
+ self ._closed = threading .Event ()
919
+ self ._stream : Optional [CancellableStream ] = None
920
+
921
+ def _can_start_streaming (self ):
922
+ if self ._closed .is_set ():
923
+ raise IOError ("Already stopped" )
924
+ if not self .container .running_container :
925
+ return False
926
+ return self .container .running_container .is_running ()
927
+
928
+ def run (self ):
929
+ try :
930
+ poll_condition (self ._can_start_streaming )
931
+ except IOError :
932
+ return
933
+ self ._stream = self .container .running_container .stream_logs ()
934
+ for line in self ._stream :
935
+ self .callback (line .rstrip (b"\r \n " ).decode ("utf-8" ))
936
+
937
+ def close (self ):
938
+ self ._closed .set ()
939
+ if self ._stream :
940
+ self ._stream .close ()
941
+
942
+
910
943
class LocalstackContainerServer (Server ):
911
- def __init__ (self , container_configuration : ContainerConfiguration | None = None ) -> None :
944
+
945
+ container : Container | RunningContainer
946
+
947
+ def __init__ (
948
+ self , container_configuration : ContainerConfiguration | Container | None = None
949
+ ) -> None :
912
950
super ().__init__ (config .EDGE_PORT , config .EDGE_BIND_HOST )
913
951
914
952
if container_configuration is None :
@@ -927,7 +965,10 @@ def __init__(self, container_configuration: ContainerConfiguration | None = None
927
965
env_vars = {},
928
966
)
929
967
930
- self .container : Container | RunningContainer = Container (container_configuration )
968
+ if isinstance (container_configuration , Container ):
969
+ self .container = container_configuration
970
+ else :
971
+ self .container = Container (container_configuration )
931
972
932
973
def is_up (self ) -> bool :
933
974
"""
@@ -1098,10 +1139,7 @@ def _init_log_printer(line):
1098
1139
print (line )
1099
1140
log_printer .callback = print
1100
1141
1101
- logfile = get_container_default_logfile_location (container_config .name )
1102
- log_printer = FileListener (logfile , callback = _init_log_printer )
1103
- log_printer .truncate_file ()
1104
- log_printer .start ()
1142
+ log_printer = ContainerLogPrinter (container , callback = _init_log_printer )
1105
1143
1106
1144
# Set up signal handler, to enable clean shutdown across different operating systems.
1107
1145
# There are subtle differences across operating systems and terminal emulators when it
@@ -1116,16 +1154,19 @@ def shutdown_handler(*args):
1116
1154
shutdown_event .set ()
1117
1155
print ("Shutting down..." )
1118
1156
server .shutdown ()
1119
- log_printer .close ()
1120
1157
1121
1158
shutdown_event = threading .Event ()
1122
1159
shutdown_event_lock = threading .RLock ()
1123
1160
signal .signal (signal .SIGINT , shutdown_handler )
1124
1161
1125
1162
# start the Localstack container as a Server
1126
- server = LocalstackContainerServer (container_config )
1163
+ server = LocalstackContainerServer (container )
1164
+ log_printer_thread = threading .Thread (
1165
+ target = log_printer .run , name = "container-log-printer" , daemon = True
1166
+ )
1127
1167
try :
1128
1168
server .start ()
1169
+ log_printer_thread .start ()
1129
1170
server .join ()
1130
1171
error = server .get_error ()
1131
1172
if error :
@@ -1134,6 +1175,8 @@ def shutdown_handler(*args):
1134
1175
except KeyboardInterrupt :
1135
1176
print ("ok, bye!" )
1136
1177
shutdown_handler ()
1178
+ finally :
1179
+ log_printer .close ()
1137
1180
1138
1181
1139
1182
def ensure_container_image (console , container : Container ):
0 commit comments