11import subprocess
22import sys
33import tempfile
4+ from multiprocessing import Process
45from pathlib import Path
56from typing import Optional
67
1516 FORK_OBSERVER_CHART ,
1617 HELM_COMMAND ,
1718 INGRESS_HELM_COMMANDS ,
19+ LOGGING_CRD_COMMANDS ,
1820 LOGGING_HELM_COMMANDS ,
1921 LOGGING_NAMESPACE ,
2022 NAMESPACES_CHART_LOCATION ,
@@ -75,17 +77,47 @@ def _deploy(directory, debug, namespace, to_all_users):
7577
7678 if to_all_users :
7779 namespaces = get_namespaces_by_type (WARGAMES_NAMESPACE_PREFIX )
80+ processes = []
7881 for namespace in namespaces :
79- deploy (directory , debug , namespace .metadata .name , False )
82+ p = Process (target = deploy , args = (directory , debug , namespace .metadata .name , False ))
83+ p .start ()
84+ processes .append (p )
85+ for p in processes :
86+ p .join ()
8087 return
8188
8289 if (directory / NETWORK_FILE ).exists ():
83- dl = deploy_logging_stack (directory , debug )
84- deploy_network (directory , debug , namespace = namespace )
85- df = deploy_fork_observer (directory , debug )
86- if dl | df :
87- deploy_ingress (debug )
88- deploy_caddy (directory , debug )
90+ processes = []
91+ # Deploy logging CRD first to avoid synchronisation issues
92+ deploy_logging_crd (directory , debug )
93+
94+ logging_process = Process (target = deploy_logging_stack , args = (directory , debug ))
95+ logging_process .start ()
96+ processes .append (logging_process )
97+
98+ network_process = Process (target = deploy_network , args = (directory , debug , namespace ))
99+ network_process .start ()
100+
101+ ingress_process = Process (target = deploy_ingress , args = (directory , debug ))
102+ ingress_process .start ()
103+ processes .append (ingress_process )
104+
105+ caddy_process = Process (target = deploy_caddy , args = (directory , debug ))
106+ caddy_process .start ()
107+ processes .append (caddy_process )
108+
109+ # Wait for the network process to complete
110+ network_process .join ()
111+
112+ # Start the fork observer process immediately after network process completes
113+ fork_observer_process = Process (target = deploy_fork_observer , args = (directory , debug ))
114+ fork_observer_process .start ()
115+ processes .append (fork_observer_process )
116+
117+ # Wait for all other processes to complete
118+ for p in processes :
119+ p .join ()
120+
89121 elif (directory / NAMESPACES_FILE ).exists ():
90122 deploy_namespaces (directory )
91123 else :
@@ -118,11 +150,30 @@ def check_logging_required(directory: Path):
118150 return False
119151
120152
153+ def deploy_logging_crd (directory : Path , debug : bool ) -> bool :
154+ """
155+ This function exists so we can parallelise the rest of the loggin stack
156+ installation
157+ """
158+ if not check_logging_required (directory ):
159+ return False
160+
161+ click .echo (
162+ "Found collectLogs or metricsExport in network definition, Deploying logging stack CRD"
163+ )
164+
165+ for command in LOGGING_CRD_COMMANDS :
166+ if not stream_command (command ):
167+ print (f"Failed to run Helm command: { command } " )
168+ return False
169+ return True
170+
171+
121172def deploy_logging_stack (directory : Path , debug : bool ) -> bool :
122173 if not check_logging_required (directory ):
123174 return False
124175
125- click .echo ("Found collectLogs or metricsExport in network definition, Deploying logging stack" )
176+ click .echo ("Deploying logging stack" )
126177
127178 for command in LOGGING_HELM_COMMANDS :
128179 if not stream_command (command ):
@@ -144,7 +195,7 @@ def deploy_caddy(directory: Path, debug: bool):
144195 if not network_file .get (name , {}).get ("enabled" , False ):
145196 return
146197
147- cmd = f"{ HELM_COMMAND } { name } { CADDY_CHART } --namespace { namespace } "
198+ cmd = f"{ HELM_COMMAND } { name } { CADDY_CHART } --namespace { namespace } --create-namespace "
148199 if debug :
149200 cmd += " --debug"
150201
@@ -156,7 +207,15 @@ def deploy_caddy(directory: Path, debug: bool):
156207 click .echo ("\n To access the warnet dashboard run:\n warnet dashboard" )
157208
158209
159- def deploy_ingress (debug : bool ):
210+ def deploy_ingress (directory : Path , debug : bool ):
211+ # Deploy ingress if either logging or fork observer is enabled
212+ network_file_path = directory / NETWORK_FILE
213+ with network_file_path .open () as f :
214+ network_file = yaml .safe_load (f )
215+ fo_enabled = network_file .get ("fork_observer" , {}).get ("enabled" , False )
216+ logging_enabled = check_logging_required (directory )
217+ if not (fo_enabled or logging_enabled ):
218+ return
160219 click .echo ("Deploying ingress controller" )
161220
162221 for command in INGRESS_HELM_COMMANDS :
@@ -231,41 +290,49 @@ def deploy_fork_observer(directory: Path, debug: bool) -> bool:
231290
232291def deploy_network (directory : Path , debug : bool = False , namespace : Optional [str ] = None ):
233292 network_file_path = directory / NETWORK_FILE
234- defaults_file_path = directory / DEFAULTS_FILE
235-
236293 namespace = get_default_namespace_or (namespace )
237294
238295 with network_file_path .open () as f :
239296 network_file = yaml .safe_load (f )
240297
298+ processes = []
241299 for node in network_file ["nodes" ]:
242- click .echo (f"Deploying node: { node .get ('name' )} " )
243- try :
244- temp_override_file_path = ""
245- node_name = node .get ("name" )
246- node_config_override = {k : v for k , v in node .items () if k != "name" }
247-
248- cmd = f"{ HELM_COMMAND } { node_name } { BITCOIN_CHART_LOCATION } --namespace { namespace } -f { defaults_file_path } "
249- if debug :
250- cmd += " --debug"
251-
252- if node_config_override :
253- with tempfile .NamedTemporaryFile (
254- mode = "w" , suffix = ".yaml" , delete = False
255- ) as temp_file :
256- yaml .dump (node_config_override , temp_file )
257- temp_override_file_path = Path (temp_file .name )
258- cmd = f"{ cmd } -f { temp_override_file_path } "
259-
260- if not stream_command (cmd ):
261- click .echo (f"Failed to run Helm command: { cmd } " )
262- return
263- except Exception as e :
264- click .echo (f"Error: { e } " )
300+ p = Process (target = deploy_single_node , args = (node , directory , debug , namespace ))
301+ p .start ()
302+ processes .append (p )
303+
304+ for p in processes :
305+ p .join ()
306+
307+
308+ def deploy_single_node (node , directory : Path , debug : bool , namespace : str ):
309+ defaults_file_path = directory / DEFAULTS_FILE
310+ click .echo (f"Deploying node: { node .get ('name' )} " )
311+ temp_override_file_path = ""
312+ try :
313+ node_name = node .get ("name" )
314+ node_config_override = {k : v for k , v in node .items () if k != "name" }
315+
316+ defaults_file_path = directory / DEFAULTS_FILE
317+ cmd = f"{ HELM_COMMAND } { node_name } { BITCOIN_CHART_LOCATION } --namespace { namespace } -f { defaults_file_path } "
318+ if debug :
319+ cmd += " --debug"
320+
321+ if node_config_override :
322+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".yaml" , delete = False ) as temp_file :
323+ yaml .dump (node_config_override , temp_file )
324+ temp_override_file_path = Path (temp_file .name )
325+ cmd = f"{ cmd } -f { temp_override_file_path } "
326+
327+ if not stream_command (cmd ):
328+ click .echo (f"Failed to run Helm command: { cmd } " )
265329 return
266- finally :
267- if temp_override_file_path :
268- Path (temp_override_file_path ).unlink ()
330+ except Exception as e :
331+ click .echo (f"Error: { e } " )
332+ return
333+ finally :
334+ if temp_override_file_path :
335+ Path (temp_override_file_path ).unlink ()
269336
270337
271338def deploy_namespaces (directory : Path ):
@@ -284,32 +351,40 @@ def deploy_namespaces(directory: Path):
284351 )
285352 return
286353
354+ processes = []
287355 for namespace in namespaces_file ["namespaces" ]:
288- click .echo (f"Deploying namespace: { namespace .get ('name' )} " )
289- try :
290- temp_override_file_path = ""
291- namespace_name = namespace .get ("name" )
292- namespace_config_override = {k : v for k , v in namespace .items () if k != "name" }
293-
294- cmd = f"{ HELM_COMMAND } { namespace_name } { NAMESPACES_CHART_LOCATION } -f { defaults_file_path } "
295-
296- if namespace_config_override :
297- with tempfile .NamedTemporaryFile (
298- mode = "w" , suffix = ".yaml" , delete = False
299- ) as temp_file :
300- yaml .dump (namespace_config_override , temp_file )
301- temp_override_file_path = Path (temp_file .name )
302- cmd = f"{ cmd } -f { temp_override_file_path } "
303-
304- if not stream_command (cmd ):
305- click .echo (f"Failed to run Helm command: { cmd } " )
306- return
307- except Exception as e :
308- click .echo (f"Error: { e } " )
356+ p = Process (target = deploy_single_namespace , args = (namespace , defaults_file_path ))
357+ p .start ()
358+ processes .append (p )
359+
360+ for p in processes :
361+ p .join ()
362+
363+
364+ def deploy_single_namespace (namespace , defaults_file_path : Path ):
365+ click .echo (f"Deploying namespace: { namespace .get ('name' )} " )
366+ temp_override_file_path = ""
367+ try :
368+ namespace_name = namespace .get ("name" )
369+ namespace_config_override = {k : v for k , v in namespace .items () if k != "name" }
370+
371+ cmd = f"{ HELM_COMMAND } { namespace_name } { NAMESPACES_CHART_LOCATION } -f { defaults_file_path } "
372+
373+ if namespace_config_override :
374+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".yaml" , delete = False ) as temp_file :
375+ yaml .dump (namespace_config_override , temp_file )
376+ temp_override_file_path = Path (temp_file .name )
377+ cmd = f"{ cmd } -f { temp_override_file_path } "
378+
379+ if not stream_command (cmd ):
380+ click .echo (f"Failed to run Helm command: { cmd } " )
309381 return
310- finally :
311- if temp_override_file_path :
312- temp_override_file_path .unlink ()
382+ except Exception as e :
383+ click .echo (f"Error: { e } " )
384+ return
385+ finally :
386+ if temp_override_file_path :
387+ Path (temp_override_file_path ).unlink ()
313388
314389
315390def is_windows ():
0 commit comments