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 }  
198+     cmd  =  f"{ HELM_COMMAND } { name } { CADDY_CHART } { 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 } { 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 } { 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 } { 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 } { 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 } { 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 } { 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 } { 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 } { 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