Plugins extend Warnet by running custom code at specific points during warnet deploy. They are declared in the plugins: section of network.yaml and invoked automatically.
plugins:
<hook>:
<plugin-name>:
entrypoint: "../plugins/<plugin-name>" # required: path to the plugin directory
<key>: <value> # any additional plugin-specific configWarnet runs <entrypoint>/plugin.py entrypoint '<plugin-config-json>' '<warnet-context-json>' for each declared plugin.
Hooks control when a plugin runs relative to the deploy sequence. All six hooks run during warnet deploy:
| Hook | When it runs |
|---|---|
preDeploy |
Before anything else is deployed |
postDeploy |
After all nodes and the network are deployed |
preNode |
Before each individual node is deployed (once per node) |
postNode |
After each individual node is deployed (once per node) |
preNetwork |
After logging infrastructure, before nodes are launched |
postNetwork |
After all node deploy threads have completed |
A plugin is a directory containing at minimum a plugin.py file. The file must accept the subcommand entrypoint with two positional JSON arguments:
import json, sys
assert sys.argv[1] == "entrypoint"
plugin_config = json.loads(sys.argv[2]) # keys declared in network.yaml
warnet_context = json.loads(sys.argv[3]) # hook_value, namespace, annexwarnet_context always contains:
| Key | Value |
|---|---|
hook_value |
The hook that fired ("preDeploy", "postNode", etc.) |
namespace |
The Kubernetes namespace being deployed into |
annex.node_name |
(preNode/postNode only) Name of the current node |
Plugins that deploy Kubernetes resources typically use Helm:
from warnet.process import run_command
from pathlib import Path
assert sys.argv[1] == "entrypoint"
plugin_config = json.loads(sys.argv[2])
command = f"helm upgrade --install my-plugin {Path(__file__).parent / 'charts' / 'my-plugin'}"
for key, value in plugin_config.items():
command += f" --set {key}={value}"
run_command(command)Start from the hello plugin included in every initialised project:
warnet init
cat plugins/hello/plugin.pyThe following plugins ship with Warnet in resources/plugins/.
SimLN generates realistic Lightning Network payment activity between nodes. It runs as a postDeploy pod and supports both LND and CLN.
plugins:
postDeploy:
simln:
entrypoint: "../plugins/simln"
activity: '[{"source": "tank-0003-ln", "destination": "tank-0005-ln", "interval_secs": 1, "amount_msat": 2000}]'The activity value is a JSON array of payment flows. Each flow specifies:
| Field | Description |
|---|---|
source |
Pod name of the sending LND/CLN node |
destination |
Pod name of the receiving node |
interval_secs |
Seconds between payment attempts |
amount_msat |
Payment amount in millisatoshis |
SimLN automatically discovers node credentials (macaroons, TLS certs) for every LND and CLN node in the network.
The SimLN plugin exposes additional commands for interacting with running instances:
# List pod names of all running SimLN instances
python3 resources/plugins/simln/plugin.py list-pod-names
# Download results from a SimLN pod to the current directory
python3 resources/plugins/simln/plugin.py download-results <pod-name>
# Get an example activity JSON for the first two LN nodes
python3 resources/plugins/simln/plugin.py get-example-activity
# Launch a new activity from the command line
python3 resources/plugins/simln/plugin.py launch-activity '<activity-json>'
# Run a shell command inside a SimLN pod
python3 resources/plugins/simln/plugin.py sh <pod-name> <command> [args...]Results written by SimLN inside the pod at /working/results/ can also be retrieved with kubectl cp.
To use a custom SimLN build, update resources/plugins/simln/charts/simln/values.yaml:
image:
repository: "myusername/sim-ln"
tag: "myversion"The Tor plugin deploys a Tor daemon (torda) as a Kubernetes service, enabling Bitcoin nodes to connect over Tor.
plugins:
preDeploy:
tor:
entrypoint: "../plugins/tor"The Tor chart does not accept additional configuration keys beyond entrypoint. See resources/plugins/tor/charts/torda/values.yaml for defaults.
The following plugin patterns appear in Warnet-based contest repos.
Deploys a scoreboard web service as a postDeploy plugin, then exposes it on the Caddy dashboard via the services: key:
plugins:
postDeploy:
leaderboard:
entrypoint: "../../plugins/leaderboard"
admin_key: "secretkey123"
next_public_asset_prefix: "/leaderboard"
services:
- title: Leaderboard
path: /leaderboard/
host: leaderboard.default
port: 3000Deploys a Kubernetes Service that routes traffic to LnVisualizer sidecar containers running inside the miner node's LND pod. Activated as preDeploy so the Service exists before the dashboard is configured:
plugins:
preDeploy:
lnvisualizer:
entrypoint: "../../plugins/lnvisualizer"
instance: miner # node whose LND pod hosts the sidecars
name: lnd-ln # Kubernetes Service name suffix
services:
- title: LN Visualizer Web UI
path: /lnvisualizer/
host: lnvisualizer.default
port: 80The sidecar containers themselves are added under lnd.extraContainers on the miner node — see LN Options.
nodes:
# ... node list ...
plugins:
preDeploy:
setup:
entrypoint: "../plugins/setup"
config_value: "foo"
postDeploy:
simln:
entrypoint: "../plugins/simln"
activity: '[{"source": "tank-0003-ln", "destination": "tank-0005-ln", "interval_secs": 1, "amount_msat": 2000}]'
preNode:
hello:
entrypoint: "../plugins/hello"
podName: "hello-pre-node"
helloTo: "preNode!"
postNode:
hello:
entrypoint: "../plugins/hello"
podName: "hello-post-node"
helloTo: "postNode!"
preNetwork:
hello:
entrypoint: "../plugins/hello"
podName: "hello-pre-network"
helloTo: "preNetwork!"
postNetwork:
hello:
entrypoint: "../plugins/hello"
podName: "hello-post-network"
helloTo: "postNetwork!"