3737
3838
3939# -----------------------------------------------
40- # CONSTANTS
40+ # Env Settings
41+ # -----------------------------------------------
42+ class Settings :
43+
44+ @staticmethod
45+ def get (key , default = None ):
46+ """
47+ Return the env var value if set, else default; returns None if not set and no default.
48+ """
49+ val = os .getenv (key )
50+
51+ if val is not None :
52+ return val
53+
54+ if default is not None :
55+ return default
56+
57+ logger .warning (f"Environment variable '{ key } ' not found and no default provided." )
58+ return None
59+
60+ # Defaults
61+ DEFAULT_SOCKETS = {
62+ "docker" : "unix:///var/run/docker.sock" ,
63+ "podman" : "unix:///run/user/1000/podman/podman.sock" ,
64+ }
65+
66+ # Settings variables
67+ LOG_LEVEL = get ("LOG_LEVEL" , "INFO" )
68+ SERIALIZED = get ("SERIALIZED" , "false" )
69+
70+ USE_GPU = get ("USE_GPU" , "false" )
71+ CONTAINER_ENGINE_EXECUTABLE = get ("CONTAINER_ENGINE_EXECUTABLE" , "docker" )
72+ GPU_DEVICE = get ("GPU_DEVICE" , "nvidia.com/gpu=all" )
73+
74+ CONTAINER_SOCKET = get ("CONTAINER_SOCKET" , DEFAULT_SOCKETS .get (CONTAINER_ENGINE_EXECUTABLE ))
75+
76+ HOST_DIRECTORY = get ("HOST_DIRECTORY" , "/tmp/codabench/" )
77+ MAX_CACHE_DIR_SIZE_GB = get ("MAX_CACHE_DIR_SIZE_GB" , 10 )
78+
79+ COMPETITION_CONTAINER_NETWORK_DISABLED = get ("COMPETITION_CONTAINER_NETWORK_DISABLED" , "False" )
80+ COMPETITION_CONTAINER_HTTP_PROXY = get ("COMPETITION_CONTAINER_HTTP_PROXY" , "" )
81+ COMPETITION_CONTAINER_HTTPS_PROXY = get ("COMPETITION_CONTAINER_HTTPS_PROXY" , "" )
82+
83+ CODALAB_IGNORE_CLEANUP_STEP = get ("CODALAB_IGNORE_CLEANUP_STEP" )
84+
85+ WORKER_BUNDLE_URL_REWRITE = get ("WORKER_BUNDLE_URL_REWRITE" , "" )
86+
87+
88+ # -----------------------------------------------
89+ # Program Kind
4190# -----------------------------------------------
4291class ProgramKind :
4392 INGESTION_PROGRAM = "ingestion_program"
@@ -74,43 +123,24 @@ class SubmissionStatus:
74123# Logging
75124# -----------------------------------------------
76125configure_logging (
77- os . environ . get ( " LOG_LEVEL" , "INFO" ), os . environ . get ( " SERIALIZED" , "false" )
126+ Settings . LOG_LEVEL , Settings . SERIALIZED
78127)
79128
80129# -----------------------------------------------
81130# Initialize Docker or Podman depending on .env
82131# -----------------------------------------------
83- if os .environ .get ("USE_GPU" , "false" ).lower () == "true" :
84- logger .info (
85- "Using "
86- + os .environ .get ("CONTAINER_ENGINE_EXECUTABLE" , "docker" ).upper ()
87- + "with GPU capabilites : "
88- + os .environ .get ("GPU_DEVICE" , "nvidia.com/gpu=all" )
89- + " network_disabled for the competition container is set to "
90- + os .environ .get ("COMPETITION_CONTAINER_NETWORK_DISABLED" , "False" )
91- )
92- else :
93- logger .info (
94- "Using "
95- + os .environ .get ("CONTAINER_ENGINE_EXECUTABLE" , "docker" ).upper ()
96- + " without GPU capabilities. "
97- + "network_disabled for the competition container is set to "
98- + os .environ .get ("COMPETITION_CONTAINER_NETWORK_DISABLED" , "False" )
99- )
100-
101- if os .environ .get ("CONTAINER_ENGINE_EXECUTABLE" , "docker" ).lower () == "docker" :
102- client = docker .APIClient (
103- base_url = os .environ .get ("CONTAINER_SOCKET" , "unix:///var/run/docker.sock" ),
104- version = "auto" ,
105- )
106- elif os .environ .get ("CONTAINER_ENGINE_EXECUTABLE" ).lower () == "podman" :
107- client = docker .APIClient (
108- base_url = os .environ .get (
109- "CONTAINER_SOCKET" , "unix:///run/user/1000/podman/podman.sock"
110- ),
111- version = "auto" ,
112- )
132+ logger .info (
133+ f"Using { Settings .CONTAINER_ENGINE_EXECUTABLE .upper ()} "
134+ f"{ 'with GPU capabilities: ' + Settings .GPU_DEVICE if Settings .USE_GPU .lower () == 'true' else 'without GPU capabilities' } . "
135+ f"Network disabled for the competition container is set to { Settings .COMPETITION_CONTAINER_NETWORK_DISABLED } "
136+ )
113137
138+ # Intializing client
139+ # NOTE: CONTAINER_SOCKET is set in Settings based on CONTAINER_ENGINE_EXECUTABLE which must has either podman or docker
140+ client = docker .APIClient (
141+ base_url = Settings .CONTAINER_SOCKET ,
142+ version = "auto" ,
143+ )
114144
115145# -----------------------------------------------
116146# Show Progress bar on downloading images
@@ -178,8 +208,8 @@ def show_progress(line, progress):
178208 total = total ,
179209 )
180210 except Exception as e :
181- if os . environ . get ( " LOG_LEVEL" , "info" ) .lower () == "debug" :
182- logger .exception ("There was an error showing the progress bar" )
211+ if Settings . LOG_LEVEL .lower () == "debug" :
212+ logger .exception (f "There was an error showing the progress bar: { e } " )
183213
184214
185215# -----------------------------------------------
@@ -206,11 +236,11 @@ def setup_celery_logging(**kwargs):
206236# Directories
207237# -----------------------------------------------
208238# Setup base directories used by all submissions
209- # note : we need to pass this directory to docker/podman so it knows where to store things!
210- HOST_DIRECTORY = os . environ . get ( " HOST_DIRECTORY" , "/tmp/codabench/" )
239+ # NOTE : we need to pass this directory to docker/podman so it knows where to store things!
240+ HOST_DIRECTORY = Settings . HOST_DIRECTORY
211241BASE_DIR = "/codabench/" # base directory inside the container
212242CACHE_DIR = os .path .join (BASE_DIR , "cache" )
213- MAX_CACHE_DIR_SIZE_GB = float (os . environ . get ( " MAX_CACHE_DIR_SIZE_GB" , 10 ) )
243+ MAX_CACHE_DIR_SIZE_GB = float (Settings . MAX_CACHE_DIR_SIZE_GB )
214244
215245
216246# -----------------------------------------------
@@ -239,7 +269,7 @@ def rewrite_bundle_url_if_needed(url):
239269
240270 Example: http://localhost:9000|http://minio:9000
241271 """
242- rule = os . getenv ( " WORKER_BUNDLE_URL_REWRITE" , "" ) .strip ()
272+ rule = Settings . WORKER_BUNDLE_URL_REWRITE .strip ()
243273 if not rule or "|" not in rule :
244274 return url
245275 src , dst = rule .split ("|" , 1 )
@@ -757,14 +787,14 @@ def _create_container(
757787 ]
758788
759789 # Configure whether or not we use the GPU. Also setting auto_remove to False because
760- if os . environ . get ( " CONTAINER_ENGINE_EXECUTABLE" , "docker" ) .lower () == "docker" :
790+ if Settings . CONTAINER_ENGINE_EXECUTABLE .lower () == "docker" :
761791 security_options = ["no-new-privileges" ]
762792 else :
763793 security_options = ["label=disable" ]
764794
765795 # Setting the device ID like this allows users to specify which gpu to use in the .env file, with all being the default if no value is given
766- device_id = [os . environ . get ( " GPU_DEVICE" , "nvidia.com/gpu=all" ) ]
767- if os . environ . get ( " USE_GPU" , "false" ) .lower () == "true" :
796+ device_id = [Settings . GPU_DEVICE ]
797+ if Settings . USE_GPU .lower () == "true" :
768798 logger .info ("Container configured with GPU capabilities" )
769799 host_config = client .create_host_config (
770800 auto_remove = False ,
@@ -789,27 +819,9 @@ def _create_container(
789819 security_opt = security_options ,
790820 )
791821
792- # Disable or not the competition container access to Internet (False by default)
793- container_network_disabled = os .environ .get (
794- "COMPETITION_CONTAINER_NETWORK_DISABLED" , ""
795- )
796-
797- # HTTP and HTTPS proxy for the competition container if needed
798- competition_container_proxy_http = os .environ .get (
799- "COMPETITION_CONTAINER_HTTP_PROXY" , ""
800- )
801- competition_container_proxy_http = (
802- "http_proxy=" + competition_container_proxy_http
803- )
804-
805- competition_container_proxy_https = os .environ .get (
806- "COMPETITION_CONTAINER_HTTPS_PROXY" , ""
807- )
808- competition_container_proxy_https = (
809- "https_proxy=" + competition_container_proxy_https
810- )
811-
812822 # Creating container
823+ # COMPETITION_CONTAINER_NETWORK_DISABLED: Disable or not the competition container access to Internet (False by default)
824+ # HTTP and HTTPS proxy for the competition container if needed
813825 container = client .create_container (
814826 self .container_image ,
815827 name = container_name ,
@@ -820,10 +832,10 @@ def _create_container(
820832 working_dir = "/app/program" ,
821833 environment = [
822834 "PYTHONUNBUFFERED=1" ,
823- competition_container_proxy_http ,
824- competition_container_proxy_https ,
835+ "http_proxy=" + Settings . COMPETITION_CONTAINER_HTTP_PROXY ,
836+ "https_proxy=" + Settings . COMPETITION_CONTAINER_HTTPS_PROXY ,
825837 ],
826- network_disabled = container_network_disabled .lower () == "true" ,
838+ network_disabled = Settings . COMPETITION_CONTAINER_NETWORK_DISABLED .lower () == "true" ,
827839 )
828840
829841 return container
@@ -868,7 +880,7 @@ async def _run_container_engine_cmd(self, container, kind):
868880 logger .error (
869881 f"There was an error trying to connect to the websocket on the codabench instance: { e } "
870882 )
871- if os . environ . get ( " LOG_LEVEL" , "info" ) .lower () == "debug" :
883+ if Settings . LOG_LEVEL .lower () == "debug" :
872884 logger .exception (e )
873885
874886 start = time .time ()
@@ -922,7 +934,7 @@ async def _run_container_engine_cmd(self, container, kind):
922934 logger .error (
923935 f"There was an error while starting the container and getting the logs: { e } "
924936 )
925- if os . environ . get ( " LOG_LEVEL" , "info" ) .lower () == "debug" :
937+ if Settings . LOG_LEVEL .lower () == "debug" :
926938 logger .exception (e )
927939
928940 # Get the return code of the competition container once done
@@ -1316,7 +1328,7 @@ def start(self):
13161328 logger .error (
13171329 f"There was a problem killing { containers_to_kill } : { e } "
13181330 )
1319- if os . environ . get ( " LOG_LEVEL" , "info" ) .lower () == "debug" :
1331+ if Settings . LOG_LEVEL .lower () == "debug" :
13201332 logger .exception (e )
13211333 # Send data to be written to ingestion/scoring std_err
13221334 self ._update_submission (execution_time_limit_exceeded_data )
@@ -1368,7 +1380,7 @@ def start(self):
13681380 logger .error (
13691381 f"There was a problem killing { containers_to_kill } : { e } "
13701382 )
1371- if os . environ . get ( " LOG_LEVEL" , "info" ) .lower () == "debug" :
1383+ if Settings . LOG_LEVEL .lower () == "debug" :
13721384 logger .exception (e )
13731385 if kind == "program" :
13741386 self .program_exit_code = return_code
@@ -1486,7 +1498,7 @@ def push_output(self):
14861498 self ._put_dir (self .scoring_result , self .output_dir )
14871499
14881500 def clean_up (self ):
1489- if os . environ . get ( " CODALAB_IGNORE_CLEANUP_STEP" ) :
1501+ if Settings . CODALAB_IGNORE_CLEANUP_STEP :
14901502 logger .warning (
14911503 f"CODALAB_IGNORE_CLEANUP_STEP mode enabled, ignoring clean up of: { self .root_dir } "
14921504 )
0 commit comments