Skip to content

Commit 030eb8a

Browse files
committed
test: cover scenarios run --admin
1 parent 7fe53ea commit 030eb8a

File tree

10 files changed

+163
-0
lines changed

10 files changed

+163
-0
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ jobs:
5252
- simln_test.py
5353
- scenarios_test.py
5454
- namespace_admin_test.py
55+
- wargames_test.py
5556
steps:
5657
- uses: actions/checkout@v4
5758
- uses: azure/[email protected]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
3+
# The base class exists inside the commander container
4+
try:
5+
from commander import Commander
6+
except Exception:
7+
from resources.scenarios.commander import Commander
8+
9+
10+
class GenOneAllNodes(Commander):
11+
def set_test_params(self):
12+
self.num_nodes = 1
13+
14+
def add_options(self, parser):
15+
parser.description = (
16+
"Attempt to generate one block on every node the scenario has access to"
17+
)
18+
parser.usage = "warnet run /path/to/generate_one_allnodes.py"
19+
20+
def run_test(self):
21+
for node in self.nodes:
22+
wallet = self.ensure_miner(node)
23+
addr = wallet.getnewaddress("bech32")
24+
self.log.info(f"node: {node.tank}")
25+
self.log.info(self.generatetoaddress(node, 1, addr))
26+
27+
28+
def main():
29+
GenOneAllNodes().main()
30+
31+
32+
if __name__ == "__main__":
33+
main()

src/warnet/control.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ def filter(path):
352352
except subprocess.CalledProcessError as e:
353353
print(f"Failed to deploy scenario commander: {scenario_name}")
354354
print(f"Error: {e.stderr}")
355+
return None
355356

356357
# upload scenario files and network data to the init container
357358
wait_for_init(name, namespace=namespace)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
users:
2+
- name: warnet-user
3+
roles:
4+
- pod-viewer
5+
- pod-manager
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
namespaces:
2+
- name: wargames-red
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
nodes:
2+
- name: armada
3+
image:
4+
tag: '27.0'
5+
addnode:
6+
- miner.default
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
global:
2+
chain: regtest
3+
image:
4+
repository: bitcoindevproject/bitcoin
5+
pullPolicy: IfNotPresent
6+
tag: '27.0'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
nodes:
2+
- name: miner
3+
image:
4+
tag: '27.0'
5+
- name: target-red
6+
addnode:
7+
- miner
8+
image:
9+
tag: '27.0'
10+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
global:
2+
chain: regtest
3+
image:
4+
repository: bitcoindevproject/bitcoin
5+
pullPolicy: IfNotPresent
6+
tag: '27.0'

test/wargames_test.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
from pathlib import Path
5+
6+
import pexpect
7+
from test_base import TestBase
8+
9+
from warnet.k8s import get_kubeconfig_value
10+
from warnet.process import stream_command
11+
12+
13+
class WargamesTest(TestBase):
14+
def __init__(self):
15+
super().__init__()
16+
self.wargame_dir = Path(os.path.dirname(__file__)) / "data" / "wargames"
17+
self.scen_src_dir = Path(os.path.dirname(__file__)).parent / "resources" / "scenarios"
18+
self.scen_test_dir = (
19+
Path(os.path.dirname(__file__)).parent / "resources" / "scenarios" / "test_scenarios"
20+
)
21+
self.initial_context = get_kubeconfig_value("{.current-context}")
22+
23+
def run_test(self):
24+
try:
25+
self.setup_battlefield()
26+
self.setup_armies()
27+
self.check_scenario_permissions()
28+
finally:
29+
self.log.info("Restoring initial_context")
30+
stream_command(f"kubectl config use-context {self.initial_context}")
31+
self.cleanup()
32+
33+
def setup_battlefield(self):
34+
self.log.info("Setting up battlefield")
35+
self.log.info(self.warnet(f"deploy {self.wargame_dir / 'networks' / 'battlefield'}"))
36+
self.wait_for_all_tanks_status(target="running")
37+
self.wait_for_all_edges()
38+
39+
def setup_armies(self):
40+
self.log.info("Deploying namespaces and armadas")
41+
self.log.info(self.warnet(f"deploy {self.wargame_dir / 'namespaces' / 'armies'}"))
42+
self.log.info(
43+
self.warnet(f"deploy {self.wargame_dir / 'networks' / 'armada'} --to-all-users")
44+
)
45+
self.wait_for_all_tanks_status(target="running")
46+
self.wait_for_all_edges()
47+
48+
def check_scenario_permissions(self):
49+
self.log.info("Admin without --admin can not command a node outside of default namespace")
50+
stream_command(
51+
f"warnet run {self.scen_test_dir / 'generate_one_allnodes.py'} --source_dir={self.scen_src_dir} --debug"
52+
)
53+
# Only miner.default and target-red.default were accesible
54+
assert self.warnet("bitcoin rpc miner getblockcount") == "2"
55+
56+
self.log.info("Admin with --admin can command all nodes in any namespace")
57+
stream_command(
58+
f"warnet run {self.scen_test_dir / 'generate_one_allnodes.py'} --source_dir={self.scen_src_dir} --admin --debug"
59+
)
60+
# armada.wargames-red, miner.default and target-red.default were accesible
61+
assert self.warnet("bitcoin rpc miner getblockcount") == "5"
62+
63+
self.log.info("Switch to wargames player context")
64+
self.log.info(self.warnet("admin create-kubeconfigs"))
65+
clicker = pexpect.spawn("warnet auth kubeconfigs/warnet-user-wargames-red-kubeconfig")
66+
while clicker.expect(["Overwrite", "Updated kubeconfig"]) == 0:
67+
print(clicker.before, clicker.after)
68+
clicker.sendline("y")
69+
print(clicker.before, clicker.after)
70+
71+
self.log.info("Player without --admin can only command the node inside their own namespace")
72+
stream_command(
73+
f"warnet run {self.scen_test_dir / 'generate_one_allnodes.py'} --source_dir={self.scen_src_dir} --debug"
74+
)
75+
# Only armada.wargames-red was (and is) accesible
76+
assert self.warnet("bitcoin rpc armada getblockcount") == "6"
77+
78+
self.log.info("Player attempting to use --admin is gonna have a bad time")
79+
stream_command(
80+
f"warnet run {self.scen_test_dir / 'generate_one_allnodes.py'} --source_dir={self.scen_src_dir} --admin --debug"
81+
)
82+
# Nothing was accesible
83+
assert self.warnet("bitcoin rpc armada getblockcount") == "6"
84+
85+
self.log.info("Restore admin context")
86+
stream_command(f"kubectl config use-context {self.initial_context}")
87+
# Sanity check
88+
assert self.warnet("bitcoin rpc miner getblockcount") == "6"
89+
90+
91+
if __name__ == "__main__":
92+
test = WargamesTest()
93+
test.run_test()

0 commit comments

Comments
 (0)