Git Product home page Git Product logo

simplism's Introduction

Simplism: a tiny HTTP server for Extism Plug-ins

image

What is Simplism?

Simplism is a tiny HTTP server to serve Extism WebAssembly plug-ins and execute/call a single WebAssembly function.

It's like the official Extism CLI, but Simplism is "serving" the Extism WebAssembly plug-in instead of running it, and call a function at every HTTP request.

πŸš€ Getting started

Install Simplism

SIMPLISM_DISTRO="Linux_arm64" # πŸ‘€ https://github.com/bots-garden/simplism/releases
VERSION="0.1.3"
wget https://github.com/bots-garden/simplism/releases/download/v${VERSION}/simplism_${SIMPLISM_DISTRO}.tar.gz -O simplism.tar.gz 
tar -xf simplism.tar.gz -C /usr/bin
rm simplism.tar.gz
simplism version

Generate a (GoLang) wasm plug-in

simplism generate golang hello ./

# hello
# β”œβ”€β”€ go.mod
# β”œβ”€β”€ main.go
# └── README.md

Build the wasm plug-in

you can follow the instructions into the hello/README.md file

cd hello
tinygo build -scheduler=none --no-debug \
-o hello.wasm \
-target wasi main.go

Serve the wasm plug-in

simplism listen \
hello.wasm handle --http-port 8080 --log-level info

Query the wasm plug-in:

curl http://localhost:8080/hello/world \
-H 'content-type: application/json; charset=utf-8' \
-d '{"firstName":"Bob","lastName":"Morane"}'

Run Simplism

Usage:
  simplism [command] [arguments]

Available Commands:
  listen      Serve an Extism plug-in function
              Arguments: [wasm file path] [function name]
  version     Display the Minism version
              Arguments: nothing
  generate    Generate a source code project of an Extism plug-in
              Arguments: [plug-in language] [project name] [project path]
              Languages: golang (or go), rustlang (or rust), javascript (or js)
              Ex: simplism generate js hello samples/javascript (it will create samples/javascript/hello/)
  config      Serve an Extism plug-in function using a yaml configuration file
              Arguments: [yaml file path] [config key]
  flock       Serve several Extism plug-in functions using a yaml configuration file
              Arguments: [yaml file path] [config key]

Flags for listen command:
  --http-port              int      HTTP port of the Simplism server (default: 8080)
  --log-level              string   Log level to print message
                                    Possible values: error, warn, info, debug, trace
  --allow-hosts            string   Hosts for HTTP request (json array) 
                                    Default: ["*"]
  --allow-paths            string   Allowed paths to write and read files (json string) 
                                    Default: {}
  --config                 string   Configuration data (json string)
                                    Default: {}
  --env                    string   Environment variables to forward to the wasm plug-in
                                    Default: []
  --wasi                   bool     Default: true
  --wasm-url               string   Url to download the wasm file
  --wasm-url-auth-header   string   Authentication header to download the wasm file, ex: "PRIVATE-TOKEN=IlovePandas"
                                    Or use this environment variable: WASM_URL_AUTH_HEADER='PRIVATE-TOKEN=IlovePandas'
  --cert-file              string   Path to certificate file (https)
  --key-file               string   Path to key file (https)
  --admin-reload-token     string   Admin token to be authorized to reload the wasm-plugin
                                    Or use this environment variable: ADMIN_RELOAD_TOKEN
                                    Use the /reload endpoint to reload the wasm-plugin
  --service-discovery      bool     The current Simplism server is a service discovery server
                                    Default: false
  --discovery-endpoint     string   The endpoint of the service discovery server
                                    It always ends with /discovery
                                    Example: http://localhost:9000/discovery
  --admin-discovery-token  string   Admin token to be authorized to post information to the service discovery server
                                    Or use this environment variable: ADMIN_DISCOVERY_TOKEN
                                    Use the /discovery endpoint to post information to the service discovery server
  --service-name           string   Name of the service (it can be useful with the service discovery mode)
  --information            string   Information about the service (it can be useful with the service discovery mode)
  --spawn-mode             bool     The current Simplism server is in spawn mode (it can create new simplism servers with the /spawn endpoint)
                                    Default: false
  --admin-spawn-token      string   Admin token to be authorized to spawn a new Simplism server
                                    Or use this environment variable: ADMIN_SPAWN_TOKEN
                                    Use the /spawn endpoint to spawn a new Simplism server
  --http-port-auto         bool     Automatically find an available port (only works in spawn mode)
                                    Default: false
  --recovery-path          string   Path of the recovery file (only works in spawn mode)
                                    Default: "recovery.yaml"
  --recovery-mode          bool     The current Simplism server is in recovery mode
                                    Default: true
  --store-mode             bool     The current Simplism server exposes a store api to save data in a bbolt database
                                    Use the /store endpoint (see documentation)
                                    Default: false
  --store-path             string   File path of the store db file  
                                    Default: file path of the wasm file + file name + ".store.db"
  --admin-store-token      string   Admin token to be authorized to use the store API of a Simplism server
                                    Or use this environment variable: ADMIN_STORE_TOKEN
  --registry-mode          bool     The current Simplism server exposes a registry api to upload wasm files
                                    Use the /registry endpoint (see documentation)
                                    Default: false
  --registry-path          string   File path of the uploaded wasm files  
  --admin-registry-token   string   Admin token to be authorized to use the registry API: POST(`/push`) and DELETE(`/remove`)
                                    Or use this environment variable: ADMIN_REGISTRY_TOKEN
  --private-registry-token string   Private registry token to be authorized to use the registry API: GET(`/pull`) and GET(`/discover`)
                                    Or use this environment variable: PRIVATE_REGISTRY_TOKEN

Remarks: look at the ./samples directory

Examples:

simplism listen ./samples/golang/simple-plugin/simple.wasm say_hello
simplism listen ./samples/golang/hello-plugin/simple.wasm say_hello \
--http-port 9090 \
--log-level info \
--allow-hosts '["*","*.google.com"]' \
--config '{"message":"πŸ‘‹ hello world 🌍"}' \
--allow-paths '{"data":"/mnt"}'

Configuration example:

# config.yml
hello-plugin:
  wasm-file: ./hello.wasm
  wasm-function: say_hello
  http-port: 8080
  log-level: info

Run the server like this: simplism config ./config.yml hello-plugin

Run Simplism in "flock" mode:

# config.yml
hello-1:
  wasm-file: ./hello.wasm
  wasm-function: say_hello
  http-port: 8081
  log-level: info
hello-2:
  wasm-file: ./hello.wasm
  wasm-function: say_hello
  http-port: 8082
  log-level: info
hello-3:
  wasm-file: ./hello.wasm
  wasm-function: say_hello
  http-port: 8083
  log-level: info

Run the servers like this: simplism flock ./config.yml. It will start 3 instances of Simplism.

See samples/flock repository for a more complex example.

Reload remotely a wasm plug-in without stopping the Simplism server

Start the Simplism server

simplism listen ./hey-one.wasm handle --http-port 8080  --admin-reload-token "1234567890"

or

export ADMIN_RELOAD_TOKEN="1234567890"
simplism listen ./hey-one.wasm handle --http-port 8080

Reload the wasm plug-in with the /reload api

curl -v -X POST \
http://localhost:8080/reload \
-H 'content-type: application/json; charset=utf-8' \
-H 'admin-reload-token:1234567890' \
-d '{"wasm-url":"http://0.0.0.0:3333/hey-two/hey-two.wasm", "wasm-file": "./hey-two.wasm", "wasm-function": "handle"}'

Service discovery

🚧 this is a work in progress

Simplism comes with a service discovery feature. It can be used to discover the running Simplism servers.

  • One of the servers (simplism service) can be a service discovery server. The service discovery server can be configured with the --service-discovery flag:
simplism listen discovery-service/discovery-service.wasm handle \
--http-port 9000 \
--log-level info \
--service-discovery true \
--admin-discovery-token people-are-strange

--admin-discovery-token is not mandatory, but it's probably a good idea to set it.

  • Then, the other services can be configured with the --discovery-endpoint flag:
simplism listen service-one/service-one.wasm handle \
--http-port 8001 \
--log-level info \
--discovery-endpoint http://localhost:9000/discovery \
--admin-discovery-token people-are-strange &

simplism listen service-two/service-two.wasm handle \
--http-port 8002 \
--log-level info \
--discovery-endpoint http://localhost:9000/discovery \
--admin-discovery-token people-are-strange &

simplism listen service-three/service-three.wasm handle \
--http-port 8003 \
--log-level info \
--discovery-endpoint http://localhost:9000/discovery \
--admin-discovery-token people-are-strange &

the 3 services will be discovered by the service discovery server. Every services will regularly post information to the service discovery server.

  • You can query the service discovery server with the /discovery endpoint to get the list of the running services:
curl http://localhost:9000/discovery \
-H 'admin-discovery-token:people-are-strange'
  • You can use the flock mode jointly with the service discovery:
service-discovery:
  wasm-file: ./discovery/discovery.wasm
  wasm-function: handle
  http-port: 9000
  log-level: info
  service-discovery: true
  admin-discovery-token: this-is-the-way

basestar-mother:
  wasm-file: ./basestar/basestar.wasm
  wasm-function: handle
  http-port: 8010
  log-level: info
  discovery-endpoint: http://localhost:9000/discovery
  admin-discovery-token: this-is-the-way

raider-1:
  wasm-file: ./raider/raider.wasm
  wasm-function: handle
  http-port: 8001
  log-level: info
  discovery-endpoint: http://localhost:9000/discovery
  admin-discovery-token: this-is-the-way

Spawn mode

🚧 this is a work in progress

If you activate the --spawn-mode flag, the Simplism server will be able tospawn a new Simplism server with the /spawn endpoint:

simplism listen ./process-spawner.wasm handle \
--http-port 8000 \
--log-level info \
--spawn-mode true \
--admin-spawn-token michael-burnham-rocks

Then, to "spawn" a new Simplism server process, you can use the /spawn endpoint with a simple curl request:

curl -X POST \
http://localhost:8080/spawn \
-H 'admin-spawn-token:michael-burnham-rocks' \
-H 'Content-Type: application/json; charset=utf-8' \
--data-binary @- << EOF
{
    "wasm-file":"../say-hello/say-hello.wasm", 
    "wasm-function":"handle", 
    "http-port":"9093", 
    "discovery-endpoint":"http://localhost:8080/discovery", 
    "admin-discovery-token":"michael-burnham-rocks"
}
EOF
echo ""

Expose and use the "store API"

start a Simplism server with the --store-mode flag:

simplism listen \
store.wasm handle \
--http-port 8080 \
--log-level info \
--store-mode true \
--admin-store-token morrison-hotel \
--information "πŸ‘‹ I'm the store service"

Query the "store API"

add records to the store:

curl http://localhost:8080/store \
-H 'content-type: application/json; charset=utf-8' \
-H 'admin-store-token: morrison-hotel' \
-d '{"key":"hello","value":"hello world"}'

curl http://localhost:8080/store \
-H 'content-type: application/json; charset=utf-8' \
-H 'admin-store-token: morrison-hotel' \
-d '{"key":"hey","value":"hey people"}'

curl http://localhost:8080/store \
-H 'content-type: application/json; charset=utf-8' \
-H 'admin-store-token: morrison-hotel' \
-d '{"key":"001","value":"first"}'

curl http://localhost:8080/store \
-H 'content-type: application/json; charset=utf-8' \
-H 'admin-store-token: morrison-hotel' \
-d '{"key":"002","value":"second"}'

curl http://localhost:8080/store \
-H 'content-type: application/json; charset=utf-8' \
-H 'admin-store-token: morrison-hotel' \
-d '{"key":"003","value":"third"}'

get all records from the store:

curl http://localhost:8080/store \
-H 'admin-store-token: morrison-hotel'

get a specific record from the store:

curl http://localhost:8080/store?key=hey \
-H 'admin-store-token: morrison-hotel'

get all records from the store with a key prefix:

curl http://localhost:8080/store?prefix=00 \
-H 'admin-store-token: morrison-hotel'

delete a specific record from the store:

curl -X "DELETE" http://localhost:8080/store?key=002 \
-H 'admin-store-token: morrison-hotel'

Generate Extism plug-in projects for Simplism

You can use Simplism to generate a project skeleton of an Extism plug-in with the following languages:

  • Golang
  • Rustlang
  • JavaScript

Generate a Golang project

simplism generate golang hello my-projects

This command will create this tree structure:

my-projects
└── hello
   β”œβ”€β”€ build.sh
   β”œβ”€β”€ Dockerfile
   β”œβ”€β”€ go.mod
   β”œβ”€β”€ main.go
   β”œβ”€β”€ query.sh
   β”œβ”€β”€ README.md
   └── run.sh

Generate a Rustlang project

simplism generate rustlang hello my-projects

This command will create this tree structure:

my-projects
└── hello
   β”œβ”€β”€ build.sh
   β”œβ”€β”€ Cargo.toml
   β”œβ”€β”€ Dockerfile
   β”œβ”€β”€ query.sh
   β”œβ”€β”€ README.md
   β”œβ”€β”€ run.sh
   └── src
      └── lib.rs

Generate a JavaScript project

simplism generate js hello my-projects

This command will create this tree structure:

my-projects
└── hello
   β”œβ”€β”€ build.sh
   β”œβ”€β”€ Dockerfile
   β”œβ”€β”€ index.d.ts
   β”œβ”€β”€ index.js
   β”œβ”€β”€ query.sh
   β”œβ”€β”€ README.md
   └── run.sh

βœ‹ more languages to come

How is Simplism developed?

Simplism is developed in Go with Wazero1 as the Wasm runtime and Extism2, which offers a Wazero-based Go SDK and a Wasm plugin system.

Prerequisites

🚧 work in progress

To develop on the Simplism project and/or create Extism plug-ins, look at .docker/compose/Dockerfile, you will find the list of the necessary softwares, libraries, tools...

πŸ‘‹ Or you can use ready to use environments

🍊 Open it with Gitpod

Build Simplism

go build
./simplism version

Write an Extism plug-in

  • Let's have a look at the official Extism documentation https://extism.org/docs/category/write-a-plug-in
  • Look into the samples directory of this repository:
    samples
    β”œβ”€β”€ golang
    β”‚  β”œβ”€β”€ hello-plugin
    β”‚  └── simple-plugin
    └── rustlang
      β”œβ”€β”€ hello-plugin
      └── simple-plugin

βœ‹ important: you can write Extism plug-ins with Go, Rust, AssemblyScript, Zig, C, Haskell and JavaScript

Footnotes

  1. Wazero is a project from Tetrate ↩

  2. Extism is a project from Dylibso ↩

simplism's People

Contributors

k33g avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

wasmlabx

simplism's Issues

πŸ“¦ prepare release

  • update the simplism version into the template generators
  • update the simplism version into the README.md
  • update the simplism version into the .release.env file
  • update the simplism version into the k8s manifests
  • update the simplism version into the Dockerfile
  • make a script for this...

πŸ€— simplify the usage of authentication header for downloading a wasm file

Right now:

  --auth-header-name  string   Authentication header name, ex: PRIVATE-TOKEN
  --auth-header-value string   Value of the authentication header, ex: IlovePandas  

It should be

  --wasm-url-auth-header string   "PRIVATE-TOKEN=IlovePandas"

And we can use an environment variable: WASM_URL_AUTH_HEADER='PRIVATE-TOKEN=IlovePandas'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.