Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin Architecture #670

Merged
merged 35 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7b43e43
Add the plugin api
mplsgrant Nov 11, 2024
c155135
enable logs and status for plugins
mplsgrant Nov 27, 2024
927cc82
improve docs
mplsgrant Nov 27, 2024
1fad8db
project: suggest setting an env var
mplsgrant Nov 27, 2024
1d9fb95
add --user-dir option for plugins
mplsgrant Nov 30, 2024
08ad2bd
clean up tags and names
mplsgrant Nov 30, 2024
42a4118
simln.py: use user_dir; tweak print statemnet
mplsgrant Dec 4, 2024
7bc7ab6
incorporate suggestions
mplsgrant Dec 4, 2024
5ba06aa
launch activity in one line
mplsgrant Dec 5, 2024
9071720
remove "warnet consumes plugin"
mplsgrant Dec 5, 2024
3f125d6
clear out constants cruft
mplsgrant Dec 5, 2024
b904879
allow simln to declare its constants
mplsgrant Dec 5, 2024
1789a53
de-dupe deploy code
mplsgrant Dec 6, 2024
77ac67c
deploy plugins from network.yaml
mplsgrant Dec 6, 2024
fcd871d
remove contract reporting
mplsgrant Dec 6, 2024
7a4ff3c
add/modify documentation; bump SimLN version
mplsgrant Dec 9, 2024
f042913
fixups
mplsgrant Dec 9, 2024
e23a728
add pre/post deploy options
mplsgrant Dec 10, 2024
0196643
fix: move run_plugins command
mplsgrant Dec 10, 2024
2bb6bbc
update relative path in plugin doc
mplsgrant Dec 11, 2024
89f4d19
add preNode/postNode; add exec/waitFor
mplsgrant Dec 12, 2024
98c002d
use entrypoint for plugins
mplsgrant Dec 13, 2024
7817cc7
parallelize run_plugins; add pre/post network
mplsgrant Dec 13, 2024
dc05443
allow plugins to take namespace and nargs
mplsgrant Dec 13, 2024
08b8c32
preNode -> postNode
mplsgrant Dec 13, 2024
0e33b48
fixup docs a little; expand test a little
mplsgrant Dec 13, 2024
ec17d24
address Max's feedback
mplsgrant Dec 13, 2024
fd80b3b
update documentation and examples
mplsgrant Dec 13, 2024
3b575d6
update documentation/examples; use PluginContent
mplsgrant Dec 13, 2024
33a9330
deploy: if no plugins, don't print
mplsgrant Dec 18, 2024
27ac1f3
deploy: simplify process checking
mplsgrant Dec 18, 2024
39da86d
incorporate many of zip's suggestions
mplsgrant Jan 3, 2025
925f17a
allow random activity by omitting activity
mplsgrant Jan 3, 2025
e351787
correct spelling in simln readme file
mplsgrant Jan 3, 2025
7311bc2
set debug = False
mplsgrant Jan 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
- rpc_test.py
- services_test.py
- signet_test.py
- simln_test.py
- scenarios_test.py
- namespace_admin_test.py
steps:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Monitor and analyze the emergent behaviors of Bitcoin networks.
- [Installation](/docs/install.md)
- [CLI Commands](/docs/warnet.md)
- [Network configuration with yaml files](/docs/config.md)
- [Plugins](/docs/plugins.md)
- [Scenarios](/docs/scenarios.md)
- [Monitoring](/docs/logging_monitoring.md)
- [Snapshots](/docs/snapshots.md)
Expand Down
72 changes: 72 additions & 0 deletions docs/plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Plugins

Plugins extend Warnet. Plugin authors can import commands from Warnet and interact with the kubernetes cluster, and plugin users can run plugins from the command line or from the `network.yaml` file.

## Activating plugins from `network.yaml`

You can activate a plugin command by placing it in the `plugins` section at the bottom of each `network.yaml` file like so:

````yaml
nodes:
<<snip>>

plugins: # This marks the beginning of the plugin section
preDeploy: # This is a hook. This particular hook will call plugins before deploying anything else.
hello: # This is the name of the plugin.
entrypoint: "../plugins/hello" # Every plugin must specify a path to its entrypoint.
podName: "hello-pre-deploy" # Plugins can have their own particular configurations, such as how to name a pod.
helloTo: "preDeploy!" # This configuration tells the hello plugin who to say "hello" to.
````

## Many kinds of hooks
There are many hooks to the Warnet `deploy` command. The example below specifies them:

````yaml
nodes:
<<snip>>

plugins:
preDeploy: # Plugins will run before any other `deploy` code.
hello:
entrypoint: "../plugins/hello"
podName: "hello-pre-deploy"
helloTo: "preDeploy!"
postDeploy: # Plugins will run after all the `deploy` code has run.
simln:
entrypoint: "../plugins/simln"
activity: '[{"source": "tank-0003-ln", "destination": "tank-0005-ln", "interval_secs": 1, "amount_msat": 2000}]'
hello:
entrypoint: "../plugins/hello"
podName: "hello-post-deploy"
helloTo: "postDeploy!"
preNode: # Plugins will run before `deploy` launches a node (once per node).
hello:
entrypoint: "../plugins/hello"
helloTo: "preNode!"
postNode: # Plugins will run after `deploy` launches a node (once per node).
hello:
entrypoint: "../plugins/hello"
helloTo: "postNode!"
preNetwork: # Plugins will run before `deploy` launches the network (essentially between logging and when nodes are deployed)
hello:
entrypoint: "../plugins/hello"
helloTo: "preNetwork!"
podName: "hello-pre-network"
postNetwork: # Plugins will run after the network deploy threads have been joined.
hello:
entrypoint: "../plugins/hello"
helloTo: "postNetwork!"
podName: "hello-post-network"
````

Warnet will execute these plugin commands during each invocation of `warnet deploy`.



## A "hello" example

To get started with an example plugin, review the `README` of the `hello` plugin found in any initialized Warnet directory:

1. `warnet init`
2. `cd plugins/hello/`

87 changes: 87 additions & 0 deletions resources/networks/hello/network.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
nodes:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to put this network here instead of /test/data ? This location will make it a "default" network that gets copied into all new warnets. Maybe the idea is to have a plugin template as a default? Either way I prefer networks that are run by tests to live in /test/data.

Especially because this network.yaml generates tons of LN activity between two specific nodes, not like general network activity. It seems less default-y

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like having the 'hello' network as as something that users get when they init a new warnet user directory because I think it's helpful to have an "all in" example for users to look at.

That said, I can understand creating a copy of the hello network in the testing directory so that all the test stuff is isolated.

- name: tank-0000
addnode:
- tank-0001
ln:
lnd: true

- name: tank-0001
addnode:
- tank-0002
ln:
lnd: true

- name: tank-0002
addnode:
- tank-0000
ln:
lnd: true

- name: tank-0003
addnode:
- tank-0000
ln:
lnd: true
lnd:
config: |
bitcoin.timelockdelta=33
channels:
- id:
block: 300
index: 1
target: tank-0004-ln
capacity: 100000
push_amt: 50000

- name: tank-0004
addnode:
- tank-0000
ln:
lnd: true
lnd:
channels:
- id:
block: 300
index: 2
target: tank-0005-ln
capacity: 50000
push_amt: 25000

- name: tank-0005
addnode:
- tank-0000
ln:
lnd: true

plugins: # Each plugin section has a number of hooks available (preDeploy, postDeploy, etc)
preDeploy: # For example, the preDeploy hook means it's plugin will run before all other deploy code
hello:
entrypoint: "../../plugins/hello" # This entrypoint path is relative to the network.yaml file
podName: "hello-pre-deploy"
helloTo: "preDeploy!"
postDeploy:
hello:
entrypoint: "../../plugins/hello"
podName: "hello-post-deploy"
helloTo: "postDeploy!"
simln: # You can have multiple plugins per hook
entrypoint: "../../plugins/simln"
activity: '[{"source": "tank-0003-ln", "destination": "tank-0005-ln", "interval_secs": 1, "amount_msat": 2000}]'
preNode: # preNode plugins run before each node is deployed
hello:
entrypoint: "../../plugins/hello"
helloTo: "preNode!"
postNode:
hello:
entrypoint: "../../plugins/hello"
helloTo: "postNode!"
preNetwork:
hello:
entrypoint: "../../plugins/hello"
helloTo: "preNetwork!"
podName: "hello-pre-network"
postNetwork:
hello:
entrypoint: "../../plugins/hello"
helloTo: "postNetwork!"
podName: "hello-post-network"
8 changes: 8 additions & 0 deletions resources/networks/hello/node-defaults.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
image:
repository: bitcoindevproject/bitcoin
pullPolicy: IfNotPresent
tag: "27.0"

lnd:
defaultConfig: |
color=#000000
Empty file added resources/plugins/__init__.py
Empty file.
124 changes: 124 additions & 0 deletions resources/plugins/hello/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Hello Plugin

## Hello World!
*Hello* is an example plugin to demonstrate the features of Warnet's plugin architecture. It uses each of the hooks available in the `warnet deploy` command (see the example below for details).

## Usage
In your python virtual environment with Warnet installed and setup, create a new Warnet user folder (follow the prompts):

`$ warnet new user_folder`

`$ cd user_folder`

Deploy the *hello* network.

`$ warnet deploy networks/hello`

While that is launching, take a look inside the `networks/hello/network.yaml` file. You can also see the copy below which includes commentary on the structure of plugins in the `network.yaml` file.

Also, take a look at the `plugins/hello/plugin.py` file to see how plugins work and to find out how to author your own plugin.

Once `deploy` completes, view the pods of the *hello* network by invoking `kubectl get all -A`.

To view the various "Hello World!" messages, run `kubectl logs pod/POD_NAME`
Comment on lines +21 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we trying to avoid kubectl commands in the docs? Lets just reccomend warnet logs -f <pod name> ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warnet logs -f <pod name> runs into an issue -- it can't determine the primary container.

We could get around this by choosing to treat the first container as the primary container.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is some logic for this already. maybe we can address in a followup:

try:
pod = get_pod(pod_name, namespace=namespace)
eligible_container_names = [BITCOINCORE_CONTAINER, COMMANDER_CONTAINER]
available_container_names = [container.name for container in pod.spec.containers]
container_name = next(
(
container_name
for container_name in available_container_names
if container_name in eligible_container_names
),
None,
)
if not container_name:
print("Could not determine primary container.")
return

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If continue using the existing logic, we would need to dictate that plugins set a PLUGIN_CONTAINER as their primary container. I'm not totally opposed to that.


### A `network.yaml` example
When you initialize a new Warnet network, Warnet will create a new `network.yaml` file. You can modify these files to fit your needs.

For example, the `network.yaml` file below includes the *hello* plugin, lightning nodes, and the *simln* plugin.

<details>
<summary>network.yaml</summary>

````yaml
nodes:
- name: tank-0000
addnode:
- tank-0001
ln:
lnd: true

- name: tank-0001
addnode:
- tank-0002
ln:
lnd: true

- name: tank-0002
addnode:
- tank-0000
ln:
lnd: true

- name: tank-0003
addnode:
- tank-0000
ln:
lnd: true
lnd:
config: |
bitcoin.timelockdelta=33
channels:
- id:
block: 300
index: 1
target: tank-0004-ln
capacity: 100000
push_amt: 50000

- name: tank-0004
addnode:
- tank-0000
ln:
lnd: true
lnd:
channels:
- id:
block: 300
index: 2
target: tank-0005-ln
capacity: 50000
push_amt: 25000

- name: tank-0005
addnode:
- tank-0000
ln:
lnd: true

plugins: # Each plugin section has a number of hooks available (preDeploy, postDeploy, etc)
preDeploy: # For example, the preDeploy hook means it's plugin will run before all other deploy code
hello:
entrypoint: "../../plugins/hello" # This entrypoint path is relative to the network.yaml file
podName: "hello-pre-deploy"
helloTo: "preDeploy!"
postDeploy:
hello:
entrypoint: "../../plugins/hello"
podName: "hello-post-deploy"
helloTo: "postDeploy!"
simln: # You can have multiple plugins per hook
entrypoint: "../../plugins/simln"
activity: '[{"source": "tank-0003-ln", "destination": "tank-0005-ln", "interval_secs": 1, "amount_msat": 2000}]'
preNode: # preNode plugins run before each node is deployed
hello:
entrypoint: "../../plugins/hello"
helloTo: "preNode!"
postNode:
hello:
entrypoint: "../../plugins/hello"
helloTo: "postNode!"
preNetwork:
hello:
entrypoint: "../../plugins/hello"
helloTo: "preNetwork!"
podName: "hello-pre-network"
postNetwork:
hello:
entrypoint: "../../plugins/hello"
helloTo: "postNetwork!"
podName: "hello-post-network"
````

</details>

5 changes: 5 additions & 0 deletions resources/plugins/hello/charts/hello/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: v2
name: hello-chart
description: A Helm chart for a hello Pod
version: 0.1.0
appVersion: "1.0"
15 changes: 15 additions & 0 deletions resources/plugins/hello/charts/hello/templates/pod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: {{ .Values.podName }}
labels:
app: {{ .Chart.Name }}
spec:
restartPolicy: Never
containers:
- name: {{ .Values.podName }}-container
image: alpine:latest
command: ["sh", "-c"]
args:
- echo "Hello {{ .Values.helloTo }}";
resources: {}
2 changes: 2 additions & 0 deletions resources/plugins/hello/charts/hello/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
podName: hello-pod
helloTo: "world"
Loading
Loading