Skip to content

Commit 3604fe2

Browse files
committed
use entrypoint for plugins
1 parent 48aad04 commit 3604fe2

File tree

5 files changed

+56
-65
lines changed

5 files changed

+56
-65
lines changed

resources/plugins/simln/README.md

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,24 +91,13 @@ nodes:
9191

9292
plugins:
9393
postDeploy:
94-
# Take note: the path to the plugin file is relative to the `network.yaml` file. The location of your `plugin.py` file and `network.yaml` file may differ than what is shown below.
95-
- "../../plugins/simln/plugin.py launch-activity '[{\"source\": \"tank-0003-ln\", \"destination\": \"tank-0005-ln\", \"interval_secs\": 1, \"amount_msat\": 2000}]'"
94+
simln:
95+
entrypoint: "../../plugins/simln" # This is the path to the simln plugin folder (relative to the network.yaml file).
96+
activity: '[{"source": "tank-0003-ln", "destination": "tank-0005-ln", "interval_secs": 1, "amount_msat": 2000}]'
9697
````
9798

9899
</details>
99100

100-
### preDeploy and postDeploy
101-
When using `warnet deploy <network folder>`, Warnet will look for a `network.yaml` in the network folder, and it will deploy the nodes listed in the `nodes` section of the file. We can choose to execute our plugin functions before Warnet deploys the nodes by including those functions in the `preDeploy` section of the `network.yaml` file. We can also choose to run plugin commands after Warnet deploys the nodes by including the function in the `postDeploy` section.
102-
103-
````yaml
104-
plugins:
105-
preDeploy:
106-
- path/to/plugin.py setup_function
107-
postDeploy:
108-
- path/to/plugin.py run
109-
- path/to/other/plugin.py run
110-
````
111-
112101

113102
## Generating your own SimLn image
114103
The SimLN plugin fetches a SimLN docker image from dockerhub. You can generate your own docker image if you choose:

resources/plugins/simln/plugin.py

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/usr/bin/env python3
2-
32
import json
43
import logging
54
import time
65
from pathlib import Path
76

87
import click
8+
import yaml
99
from kubernetes.stream import stream
1010

1111
# When we want to select pods based on their role in Warnet, we use "mission" tags. The "mission"
@@ -31,7 +31,7 @@
3131
PLUGIN_DIR_TAG = "plugin_dir"
3232

3333

34-
class SimLNError(Exception):
34+
class PluginError(Exception):
3535
pass
3636

3737

@@ -56,6 +56,38 @@ def simln(ctx):
5656
ctx.obj[PLUGIN_DIR_TAG] = Path(plugin_dir)
5757

5858

59+
@simln.command()
60+
@click.argument("network_file_path", type=str)
61+
@click.argument("hook_value", type=str)
62+
@click.pass_context
63+
def entrypoint(ctx, network_file_path: str, hook_value: str):
64+
"""Plugin entrypoint"""
65+
network_file_path = Path(network_file_path)
66+
with network_file_path.open() as f:
67+
network_file = yaml.safe_load(f) or {}
68+
if not isinstance(network_file, dict):
69+
raise ValueError(f"Invalid network file structure: {network_file_path}")
70+
71+
plugins_section = network_file.get("plugins", {})
72+
hook_section = plugins_section.get(hook_value, {})
73+
74+
plugin_name = Path(__file__).resolve().parent.stem
75+
plugin_data = hook_section.get(plugin_name)
76+
if not plugin_data:
77+
raise PluginError(f"Could not find {plugin_name} in {network_file_path}")
78+
79+
_entrypoint(ctx, plugin_data)
80+
81+
82+
def _entrypoint(ctx, plugin_data: dict):
83+
""" "Called by entrypoint"""
84+
# write your plugin startup commands here
85+
activity = plugin_data.get("activity")
86+
activity = json.loads(activity)
87+
print(activity)
88+
_launch_activity(activity, ctx.obj.get(PLUGIN_DIR_TAG))
89+
90+
5991
# The group name is then used in decorators to create commands. These commands are
6092
# available to users when they access your plugin from the command line.
6193
@simln.command()
@@ -82,7 +114,7 @@ def _get_example_activity() -> list[dict]:
82114
pod_a = pods[1].metadata.name
83115
pod_b = pods[2].metadata.name
84116
except Exception as err:
85-
raise SimLNError(
117+
raise PluginError(
86118
"Could not access the lightning nodes needed for the example.\n Try deploying some."
87119
) from err
88120
return [{"source": pod_a, "destination": pod_b, "interval_secs": 1, "amount_msat": 2000}]
@@ -116,10 +148,11 @@ def _launch_activity(activity: list[dict], plugin_dir: str) -> str:
116148
name = f"simln-{timestamp}"
117149

118150
command = f"helm upgrade --install {timestamp} {plugin_dir}/charts/simln"
119-
run_command(command)
120151

152+
run_command(command)
121153
activity_json = _generate_activity_json(activity)
122154
wait_for_init(name, namespace=get_default_namespace(), quiet=True)
155+
123156
if write_file_to_container(
124157
name,
125158
"init",
@@ -130,7 +163,7 @@ def _launch_activity(activity: list[dict], plugin_dir: str) -> str:
130163
):
131164
return name
132165
else:
133-
raise SimLNError(f"Could not write sim.json to the init container: {name}")
166+
raise PluginError(f"Could not write sim.json to the init container: {name}")
134167

135168

136169
def _generate_activity_json(activity: list[dict]) -> str:

src/warnet/constants.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ class HookValue(Enum):
3434
POST_NODE = "postNode"
3535

3636

37-
class HookOptions(Enum):
38-
EXEC = "exec"
39-
WAIT_FOR = "waitFor"
40-
41-
4237
# Directories and files for non-python assets, e.g., helm charts, example scenarios, default configs
4338
SRC_DIR = files("warnet")
4439
RESOURCES_DIR = files("resources")

src/warnet/deploy.py

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
NETWORK_FILE,
2626
SCENARIOS_DIR,
2727
WARGAMES_NAMESPACE_PREFIX,
28-
HookOptions,
2928
HookValue,
3029
)
3130
from .control import _run
@@ -37,7 +36,7 @@
3736
wait_for_ingress_controller,
3837
wait_for_pod_ready,
3938
)
40-
from .process import run_command, stream_command, wait_for_run
39+
from .process import run_command, stream_command
4140

4241
HINT = "\nAre you trying to run a scenario? See `warnet run --help`"
4342

@@ -145,40 +144,22 @@ def is_relative(path: str) -> bool:
145144
raise ValueError(f"Invalid network file structure: {network_file_path}")
146145

147146
plugins_section = network_file.get("plugins", {})
148-
plugins = plugins_section.get(hook_value.value) or []
149-
for plugin_cmd in plugins:
147+
hook_section = plugins_section.get(hook_value.value, {})
148+
for plugin_cmd in hook_section.items():
150149
match plugin_cmd:
151-
case {HookOptions.EXEC.value: cmd, HookOptions.WAIT_FOR.value: predicate}:
152-
if is_relative(cmd):
153-
cmd = network_file_path.parent / cmd
154-
print(f"{HookOptions.EXEC.value}: {cmd}")
155-
156-
if is_relative(predicate):
157-
predicate = network_file_path.parent / predicate
158-
print(f"{HookOptions.WAIT_FOR.value}: {predicate}")
159-
160-
wait_for_run(str(predicate))
161-
print(run_command(str(cmd)))
162-
163-
case {HookOptions.EXEC.value: cmd}:
164-
if is_relative(cmd):
165-
cmd = network_file_path.parent / cmd
166-
print(f"{HookOptions.EXEC.value}: {cmd}")
167-
print(run_command(str(cmd)))
168-
169-
case str():
170-
cmd = plugin_cmd
171-
if is_relative(cmd):
172-
cmd = network_file_path.parent / plugin_cmd
173-
print(f"{cmd}")
174-
print(run_command(str(cmd)))
150+
case (str(), dict()):
151+
try:
152+
entrypoint_path = Path(plugin_cmd[1].get("entrypoint"))
153+
except Exception as err:
154+
raise SyntaxError("Each plugin must have an 'entrypoint'") from err
155+
cmd = f"{network_file_path.parent / entrypoint_path / Path('plugin.py')} entrypoint {network_file_path} {hook_value.value}"
156+
print(f"Command: {cmd}")
157+
print(run_command(cmd))
175158

176159
case _:
177160
print(
178161
f"The following plugin command does not match known plugin command structures: {plugin_cmd}"
179162
)
180-
print(f"Known hook values: {[v.value for v in HookValue]}")
181-
print(f"Known hook options: {[v.value for v in HookOptions]}")
182163
sys.exit(1)
183164

184165

test/data/ln/network.yaml

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,8 @@ nodes:
5454
lnd: true
5555

5656
plugins:
57-
preNode:
58-
- "echo This is preNode"
59-
postNode:
60-
- exec: "echo This is postNode"
61-
- exec: "echo This is also postNode, but we waited for 'warnet status'"
62-
waitFor: "warnet status"
63-
preDeploy:
64-
- "echo This is preDeploy"
6557
postDeploy:
66-
- "../../../resources/plugins/simln/plugin.py launch-activity '[{\"source\": \"tank-0003-ln\", \"destination\": \"tank-0005-ln\", \"interval_secs\": 1, \"amount_msat\": 2000}]'"
67-
- exec: "../../../resources/plugins/simln/plugin.py list-pod-names"
68-
waitFor: "../../../resources/plugins/simln/plugin.py get-example-activity"
58+
simln:
59+
entrypoint: "../../../resources/plugins/simln"
60+
activity: '[{"source": "tank-0003-ln", "destination": "tank-0005-ln", "interval_secs": 1, "amount_msat": 2000}]'
61+

0 commit comments

Comments
 (0)