11import json
22import shutil
3- import tempfile
43from importlib .resources import files
54from pathlib import Path
65
7- import click
8- import yaml
96from rich import print
107
118from .bitcoin import _rpc
12- from .k8s import delete_namespace , get_default_namespace , get_mission , get_pods
9+ from .k8s import get_mission
1310from .process import stream_command
1411
1512WAR_MANIFESTS_FILES = files ("resources.manifests" )
2623BITCOIN_CHART_LOCATION = str (files ("resources.charts" ).joinpath ("bitcoincore" ))
2724
2825
29- @click .group (name = "network" )
30- def network ():
31- """Network commands"""
32-
33-
34- class Edge :
35- def __init__ (self , src : str , dst : str , data : dict [str , any ]):
36- self .src = src
37- self .dst = dst
38- self .data = data
39-
40- def to_dict (self ):
41- return {"src" : self .src , "dst" : self .dst , "data" : self .data }
42-
43-
44- def edges_from_network_file (network_file : dict [str , any ]) -> list [Edge ]:
45- edges = []
46- for node in network_file ["nodes" ]:
47- if "connect" in node :
48- for connection in node ["connect" ]:
49- edges .append (Edge (node ["name" ], connection , "" ))
50- return edges
51-
52-
5326def setup_logging_helm () -> bool :
5427 helm_commands = [
5528 "helm repo add grafana https://grafana.github.io/helm-charts" ,
@@ -104,76 +77,6 @@ def copy_scenario_defaults(directory: Path):
10477 )
10578
10679
107- @network .command ()
108- @click .argument (
109- "network_dir" ,
110- type = click .Path (exists = True , file_okay = False , dir_okay = True , path_type = Path ),
111- )
112- @click .option ("--logging/--no-logging" , default = False )
113- def deploy (network_dir : Path , logging : bool ):
114- """Deploy a warnet with topology loaded from <network_dir>"""
115- network_file_path = network_dir / NETWORK_FILE
116- defaults_file_path = network_dir / DEFAULTS_FILE
117-
118- with network_file_path .open () as f :
119- network_file = yaml .safe_load (f )
120-
121- namespace = get_default_namespace ()
122-
123- for node in network_file ["nodes" ]:
124- print (f"Deploying node: { node .get ('name' )} " )
125- try :
126- temp_override_file_path = ""
127- node_name = node .get ("name" )
128- # all the keys apart from name
129- node_config_override = {k : v for k , v in node .items () if k != "name" }
130-
131- cmd = f"{ HELM_COMMAND } { node_name } { BITCOIN_CHART_LOCATION } --namespace { namespace } -f { defaults_file_path } "
132-
133- if node_config_override :
134- with tempfile .NamedTemporaryFile (
135- mode = "w" , suffix = ".yaml" , delete = False
136- ) as temp_file :
137- yaml .dump (node_config_override , temp_file )
138- temp_override_file_path = Path (temp_file .name )
139- cmd = f"{ cmd } -f { temp_override_file_path } "
140-
141- if not stream_command (cmd ):
142- print (f"Failed to run Helm command: { cmd } " )
143- return
144- except Exception as e :
145- print (f"Error: { e } " )
146- return
147- finally :
148- if temp_override_file_path :
149- Path (temp_override_file_path ).unlink ()
150-
151-
152- @network .command ()
153- def down ():
154- """Bring down a running warnet"""
155- if delete_namespace ("warnet-logging" ):
156- print ("Warnet logging deleted" )
157- else :
158- print ("Warnet logging NOT deleted" )
159- tanks = get_mission ("tank" )
160- for tank in tanks :
161- cmd = f"helm uninstall { tank .metadata .name } "
162- stream_command (cmd )
163- # Clean up scenarios and other pods
164- # TODO: scenarios should be helm-ified as well
165- pods = get_pods ()
166- for pod in pods .items :
167- cmd = f"kubectl delete pod { pod .metadata .name } "
168- stream_command (cmd )
169-
170-
171- @network .command ()
172- def connected ():
173- """Determine if all p2p connections defined in graph are established"""
174- print (_connected ())
175-
176-
17780def _connected ():
17881 tanks = get_mission ("tank" )
17982 for tank in tanks :
@@ -193,22 +96,3 @@ def _connected():
19396 return False
19497 print ("Network connected" )
19598 return True
196-
197-
198- @network .command ()
199- def status ():
200- """Return pod status"""
201- # TODO: make it a pretty table
202- print (_status ())
203-
204-
205- def _status ():
206- tanks = get_mission ("tank" )
207- stats = []
208- for tank in tanks :
209- status = {
210- "tank" : tank .metadata .name ,
211- "bitcoin_status" : tank .status .phase .lower (),
212- }
213- stats .append (status )
214- return stats
0 commit comments