4
4
import sys
5
5
from pathlib import Path
6
6
7
+ from rich import print
8
+ from rich .console import Console
9
+ from rich .table import Table
10
+
7
11
import click
8
12
import inquirer
9
13
import yaml
@@ -24,9 +28,7 @@ def graph():
24
28
25
29
26
30
def custom_graph (
27
- num_nodes : int ,
28
- num_connections : int ,
29
- version : str ,
31
+ tanks : list ,
30
32
datadir : Path ,
31
33
fork_observer : bool ,
32
34
fork_obs_query_interval : int ,
@@ -43,30 +45,39 @@ def custom_graph(
43
45
# Generate network.yaml
44
46
nodes = []
45
47
connections = set ()
48
+ total_count = sum (int (entry ["count" ]) for entry in tanks )
49
+ index = 0
46
50
47
- for i in range (num_nodes ):
48
- node = {"name" : f"tank-{ i :04d} " , "addnode" : []}
49
-
50
- # Add round-robin connection
51
- next_node = (i + 1 ) % num_nodes
52
- node ["addnode" ].append (f"tank-{ next_node :04d} " )
53
- connections .add ((i , next_node ))
54
-
55
- # Add random connections
56
- available_nodes = list (range (num_nodes ))
57
- available_nodes .remove (i )
58
- if next_node in available_nodes :
59
- available_nodes .remove (next_node )
60
-
61
- for _ in range (min (num_connections - 1 , len (available_nodes ))):
62
- random_node = random .choice (available_nodes )
63
- # Avoid circular loops of A -> B -> A
64
- if (random_node , i ) not in connections :
65
- node ["addnode" ].append (f"tank-{ random_node :04d} " )
66
- connections .add ((i , random_node ))
67
- available_nodes .remove (random_node )
68
-
69
- nodes .append (node )
51
+ for entry in tanks :
52
+ for i in range (int (entry ["count" ])):
53
+ if ":" in entry ["version" ] and "/" in entry ["version" ]:
54
+ repo , tag = entry ["version" ].split (":" )
55
+ image = {"repository" : repo , "tag" : tag }
56
+ else :
57
+ image = {"tag" : entry ["version" ]}
58
+ node = {"name" : f"tank-{ index :04d} " , "addnode" : [], "image" : image }
59
+
60
+ # Add round-robin connection
61
+ next_node = (index + 1 ) % total_count
62
+ node ["addnode" ].append (f"tank-{ next_node :04d} " )
63
+ connections .add ((index , next_node ))
64
+
65
+ # Add random connections
66
+ available_nodes = list (range (total_count ))
67
+ available_nodes .remove (index )
68
+ if next_node in available_nodes :
69
+ available_nodes .remove (next_node )
70
+
71
+ for _ in range (min (int (entry ["connections" ]) - 1 , len (available_nodes ))):
72
+ random_node = random .choice (available_nodes )
73
+ # Avoid circular loops of A -> B -> A
74
+ if (random_node , index ) not in connections :
75
+ node ["addnode" ].append (f"tank-{ random_node :04d} " )
76
+ connections .add ((index , random_node ))
77
+ available_nodes .remove (random_node )
78
+
79
+ nodes .append (node )
80
+ index += 1
70
81
71
82
network_yaml_data = {"nodes" : nodes }
72
83
network_yaml_data ["fork_observer" ] = {
@@ -86,7 +97,6 @@ def custom_graph(
86
97
"image" : {
87
98
"repository" : DEFAULT_IMAGE_REPO ,
88
99
"pullPolicy" : "IfNotPresent" ,
89
- "tag" : version
90
100
},
91
101
"defaultConfig" :
92
102
f"rpcauth={ FORK_OBSERVER_RPCAUTH } \n " +
@@ -108,73 +118,104 @@ def custom_graph(
108
118
109
119
110
120
def inquirer_create_network (project_path : Path ):
111
- # Custom network configuration
112
- questions = [
121
+ network_name_prompt = inquirer .prompt ([
113
122
inquirer .Text (
114
123
"network_name" ,
115
124
message = click .style ("Enter your network name" , fg = "blue" , bold = True ),
116
125
validate = lambda _ , x : len (x ) > 0 ,
117
- ),
118
- inquirer .List (
119
- "nodes" ,
120
- message = click .style ("How many nodes would you like?" , fg = "blue" , bold = True ),
121
- choices = ["8" , "12" , "20" , "50" , "other" ],
122
- default = "12" ,
123
- ),
124
- inquirer .List (
125
- "connections" ,
126
- message = click .style (
127
- "How many connections would you like each node to have?" ,
128
- fg = "blue" ,
129
- bold = True ,
130
- ),
131
- choices = ["0" , "1" , "2" , "8" , "12" , "other" ],
132
- default = "8" ,
133
- ),
134
- inquirer .List (
135
- "version" ,
136
- message = click .style (
137
- "Which version would you like nodes to run by default?" , fg = "blue" , bold = True
138
- ),
139
- choices = SUPPORTED_TAGS ,
140
- default = DEFAULT_TAG ,
141
- ),
142
- ]
143
-
144
- net_answers = inquirer .prompt (questions )
145
- if net_answers is None :
126
+ )])
127
+ if not network_name_prompt :
146
128
click .secho ("Setup cancelled by user." , fg = "yellow" )
147
129
return False
148
130
149
- if net_answers ["nodes" ] == "other" :
150
- custom_nodes = inquirer .prompt (
151
- [
152
- inquirer .Text (
153
- "nodes" ,
154
- message = click .style ("Enter the number of nodes" , fg = "blue" , bold = True ),
155
- validate = lambda _ , x : int (x ) > 0 ,
156
- )
157
- ]
158
- )
159
- if custom_nodes is None :
131
+ tanks = []
132
+ while True :
133
+ table = Table (title = "Current Network Population" , show_header = True , header_style = "magenta" )
134
+ table .add_column ("Version" , style = "cyan" )
135
+ table .add_column ("Count" , style = "green" )
136
+ table .add_column ("Connections" , style = "green" )
137
+
138
+ for entry in tanks :
139
+ table .add_row (entry ["version" ], entry ["count" ], entry ["connections" ])
140
+
141
+ Console ().print (table )
142
+
143
+ add_more_prompt = inquirer .prompt ([
144
+ inquirer .List (
145
+ "add_more" ,
146
+ message = click .style (f"How many nodes to add? (0 = done)" , fg = "blue" , bold = True ),
147
+ choices = ["0" , "4" , "8" , "12" , "20" , "50" , "other" ],
148
+ default = "12" )])
149
+ if not add_more_prompt :
160
150
click .secho ("Setup cancelled by user." , fg = "yellow" )
161
151
return False
162
- net_answers ["nodes" ] = custom_nodes ["nodes" ]
152
+ if add_more_prompt ["add_more" ].startswith ("0" ):
153
+ break
163
154
164
- if net_answers ["connections" ] == "other" :
165
- custom_connections = inquirer .prompt (
166
- [
155
+ if add_more_prompt ["add_more" ] == "other" :
156
+ how_many_prompt = inquirer .prompt ([
167
157
inquirer .Text (
168
- "connections" ,
169
- message = click .style ("Enter the number of connections" , fg = "blue" , bold = True ),
170
- validate = lambda _ , x : int (x ) >= 0 ,
171
- )
172
- ]
173
- )
174
- if custom_connections is None :
158
+ "how_many" ,
159
+ message = click .style ("Enter the number of nodes" , fg = "blue" , bold = True ),
160
+ validate = lambda _ , x : int (x ) > 0 )])
161
+ if not how_many_prompt :
162
+ click .secho ("Setup cancelled by user." , fg = "yellow" )
163
+ return False
164
+ how_many = how_many_prompt ["how_many" ]
165
+ else :
166
+ how_many = add_more_prompt ["add_more" ]
167
+
168
+ tank_details_prompt = inquirer .prompt ([
169
+ inquirer .List (
170
+ "version" ,
171
+ message = click .style ("Which version would you like to add to network?" , fg = "blue" , bold = True ),
172
+ choices = ["other" ] + SUPPORTED_TAGS ,
173
+ default = DEFAULT_TAG ,
174
+ ),
175
+ inquirer .List (
176
+ "connections" ,
177
+ message = click .style (
178
+ "How many connections would you like each of these nodes to have?" ,
179
+ fg = "blue" ,
180
+ bold = True ,
181
+ ),
182
+ choices = ["0" , "1" , "2" , "8" , "12" , "other" ],
183
+ default = "8" ,
184
+ )])
185
+ if not tank_details_prompt :
175
186
click .secho ("Setup cancelled by user." , fg = "yellow" )
176
187
return False
177
- net_answers ["connections" ] = custom_connections ["connections" ]
188
+ break
189
+ if tank_details_prompt ["version" ] == "other" :
190
+ custom_version_prompt = inquirer .prompt ([
191
+ inquirer .Text (
192
+ "version" ,
193
+ message = click .style ("Provide dockerhub repository/image:tag" , fg = "blue" , bold = True ),
194
+ validate = lambda _ , x : "/" in x and ":" in x )])
195
+ if not custom_version_prompt :
196
+ click .secho ("Setup cancelled by user." , fg = "yellow" )
197
+ return False
198
+ tank_details_prompt ["version" ] = custom_version_prompt ["version" ]
199
+
200
+ if tank_details_prompt ["connections" ] == "other" :
201
+ how_many_conn_prompt = inquirer .prompt ([
202
+ inquirer .Text (
203
+ "how_many_conn" ,
204
+ message = click .style ("Enter the number of connections" , fg = "blue" , bold = True ),
205
+ validate = lambda _ , x : int (x ) > 0 )])
206
+ if not how_many_conn_prompt :
207
+ click .secho ("Setup cancelled by user." , fg = "yellow" )
208
+ return False
209
+ how_many_conn = how_many_conn_prompt ["how_many_conn" ]
210
+ else :
211
+ how_many_conn = tank_details_prompt ["connections" ]
212
+
213
+ tanks .append ({
214
+ "version" : tank_details_prompt ["version" ],
215
+ "count" : how_many ,
216
+ "connections" : how_many_conn
217
+ })
218
+
178
219
fork_observer = click .prompt (
179
220
click .style (
180
221
"\n Would you like to enable fork-observer on the network?" , fg = "blue" , bold = True
@@ -202,12 +243,10 @@ def inquirer_create_network(project_path: Path):
202
243
default = False ,
203
244
)
204
245
caddy = fork_observer | logging
205
- custom_network_path = project_path / "networks" / net_answers ["network_name" ]
246
+ custom_network_path = project_path / "networks" / network_name_prompt ["network_name" ]
206
247
click .secho ("\n Generating custom network..." , fg = "yellow" , bold = True )
207
248
custom_graph (
208
- int (net_answers ["nodes" ]),
209
- int (net_answers ["connections" ]),
210
- net_answers ["version" ],
249
+ tanks ,
211
250
custom_network_path ,
212
251
fork_observer ,
213
252
fork_observer_query_interval ,
0 commit comments