Skip to content

Commit e285997

Browse files
authored
Merge pull request #321 from pinheadmz/graph-cli
cli: move all graph RPCs out of server, to warcli
2 parents cfe8dcc + 0ed84b0 commit e285997

File tree

3 files changed

+33
-82
lines changed

3 files changed

+33
-82
lines changed

src/cli/graph.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
from io import BytesIO
12
from pathlib import Path
23

34
import click
4-
from cli.rpc import rpc_call
5+
import networkx as nx
56
from rich import print
6-
from warnet.utils import DEFAULT_TAG
7+
from warnet.utils import DEFAULT_TAG, create_cycle_graph, validate_graph_schema
78

89

910
@click.group(name="graph")
@@ -19,21 +20,19 @@ def graph():
1920
@click.option("--random", is_flag=True)
2021
def create(number: int, outfile: Path, version: str, bitcoin_conf: Path, random: bool = False):
2122
"""
22-
Create a cycle graph with <n> nodes, and additionally include 7 extra random outbounds per node.
23+
Create a cycle graph with <number> nodes, and include 7 extra random outbounds per node.
2324
Returns XML file as string with or without --outfile option
2425
"""
25-
print(
26-
rpc_call(
27-
"graph_generate",
28-
{
29-
"n": number,
30-
"outfile": str(outfile) if outfile else "",
31-
"version": version,
32-
"bitcoin_conf": str(bitcoin_conf),
33-
"random": random,
34-
},
35-
)
36-
)
26+
graph = create_cycle_graph(number, version, bitcoin_conf, random)
27+
28+
if outfile:
29+
file_path = Path(outfile)
30+
nx.write_graphml(graph, file_path, named_key_ids=True)
31+
return f"Generated graph written to file: {outfile}"
32+
bio = BytesIO()
33+
nx.write_graphml(graph, bio, named_key_ids=True)
34+
xml_data = bio.getvalue()
35+
print(xml_data.decode("utf-8"))
3736

3837

3938
@graph.command()
@@ -42,4 +41,6 @@ def validate(graph: Path):
4241
"""
4342
Validate a <graph file> against the schema.
4443
"""
45-
print(rpc_call("graph_validate", {"graph_path": Path(graph).as_posix()}))
44+
with open(graph) as f:
45+
graph = nx.parse_graphml(f.read(), node_type=int)
46+
return validate_graph_schema(graph)

src/warnet/server.py

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,14 @@
1515
import time
1616
import traceback
1717
from datetime import datetime
18-
from io import BytesIO
1918
from pathlib import Path
2019

21-
import jsonschema
22-
import networkx as nx
2320
import scenarios
2421
from backends import ServiceType
2522
from flask import Flask, jsonify, request
2623
from flask_jsonrpc.app import JSONRPC
2724
from flask_jsonrpc.exceptions import ServerError
28-
from warnet.utils import (
29-
create_cycle_graph,
30-
gen_config_dir,
31-
validate_graph_schema,
32-
)
25+
from warnet.utils import gen_config_dir
3326
from warnet.warnet import Warnet
3427

3528
WARNET_SERVER_PORT = 9276
@@ -168,9 +161,6 @@ def setup_rpc(self):
168161
self.jsonrpc.register(self.network_status)
169162
self.jsonrpc.register(self.network_connected)
170163
self.jsonrpc.register(self.network_export)
171-
# Graph
172-
self.jsonrpc.register(self.graph_generate)
173-
self.jsonrpc.register(self.graph_validate)
174164
# Debug
175165
self.jsonrpc.register(self.generate_deployment)
176166
self.jsonrpc.register(self.exec_run)
@@ -505,39 +495,6 @@ def thread_start(server: Server, network):
505495
self.logger.error(msg)
506496
raise ServerError(message=msg) from e
507497

508-
def graph_generate(
509-
self,
510-
n: int,
511-
outfile: str,
512-
version: str,
513-
bitcoin_conf: str | None = None,
514-
random: bool = False,
515-
) -> str:
516-
try:
517-
graph = create_cycle_graph(n, version, bitcoin_conf, random)
518-
519-
if outfile:
520-
file_path = Path(outfile)
521-
nx.write_graphml(graph, file_path, named_key_ids=True)
522-
return f"Generated graph written to file: {outfile}"
523-
bio = BytesIO()
524-
nx.write_graphml(graph, bio, named_key_ids=True)
525-
xml_data = bio.getvalue()
526-
return xml_data.decode("utf-8")
527-
except Exception as e:
528-
msg = f"Error generating graph: {e}"
529-
self.logger.error(msg)
530-
raise ServerError(message=msg) from e
531-
532-
def graph_validate(self, graph_path: str) -> str:
533-
with open(graph_path) as f:
534-
graph = nx.parse_graphml(f.read(), node_type=int, force_multigraph=True)
535-
try:
536-
validate_graph_schema(graph)
537-
except (jsonschema.ValidationError, jsonschema.SchemaError) as e:
538-
raise ServerError(message=f"Schema of {graph_path} is invalid: {e}") from e
539-
return f"Schema of {graph_path} is valid"
540-
541498
def network_down(self, network: str = "warnet") -> str:
542499
"""
543500
Stop all containers in <network>.

test/graph_test.py

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,23 @@
77
from warnet.utils import DEFAULT_TAG
88

99
base = TestBase()
10-
base.network = False
11-
base.start_server()
1210

13-
with tempfile.TemporaryDirectory() as dir:
14-
tf = f"{dir}/{str(uuid.uuid4())}.graphml"
15-
if base.backend == "compose":
16-
print(f"Server writing test graph directly to {tf}")
17-
print(base.warcli(f"graph create 10 --outfile={tf} --version={DEFAULT_TAG}", network=False))
18-
base.wait_for_predicate(lambda: Path(tf).exists())
19-
else:
20-
print(f"Client retrieving test graph from RPC and writing to {tf}")
21-
xml = base.warcli(f"graph create 10 --version={DEFAULT_TAG}", network=False)
22-
print(xml)
23-
with open(tf, "w") as file:
24-
file.write(xml)
11+
# Does not require a running Warnet RPC server yet
12+
test_dir = tempfile.TemporaryDirectory()
13+
tf = f"{test_dir.name}/{str(uuid.uuid4())}.graphml"
2514

26-
# Validate the graph schema
27-
assert "invalid" not in base.warcli(f"graph validate {Path(tf)}", False)
28-
print(f"Graph at {tf} validated successfully")
15+
print(f"CLI tool writing test graph directly to {tf}")
16+
print(base.warcli(f"graph create 10 --outfile={tf} --version={DEFAULT_TAG}", network=False))
17+
base.wait_for_predicate(lambda: Path(tf).exists())
2918

30-
# Test that the graph actually works
31-
print(base.warcli(f"network start {Path(tf)}"))
32-
base.wait_for_all_tanks_status(target="running")
33-
base.wait_for_all_edges()
34-
base.warcli("rpc 0 getblockcount")
19+
# Validate the graph schema
20+
assert "invalid" not in base.warcli(f"graph validate {Path(tf)}", False)
21+
print(f"Graph at {tf} validated successfully")
3522

23+
# Test that the graph actually works, now we need a server
24+
base.start_server()
25+
print(base.warcli(f"network start {Path(tf)}"))
26+
base.wait_for_all_tanks_status(target="running")
27+
base.wait_for_all_edges()
28+
base.warcli("rpc 0 getblockcount")
3629
base.stop_server()

0 commit comments

Comments
 (0)