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

super basic wasm filter implementation using wazero #2947

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 2 additions & 0 deletions filters/builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/zalando/skipper/filters/tee"
"github.com/zalando/skipper/filters/tls"
"github.com/zalando/skipper/filters/tracing"
"github.com/zalando/skipper/filters/wasm"
"github.com/zalando/skipper/filters/xforward"
"github.com/zalando/skipper/script"
)
Expand Down Expand Up @@ -230,6 +231,7 @@ func Filters() []filters.Spec {
consistenthash.NewConsistentHashKey(),
consistenthash.NewConsistentHashBalanceFactor(),
tls.New(),
wasm.NewWASM(),
}
}

Expand Down
1 change: 1 addition & 0 deletions filters/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ const (
OpaServeResponseName = "opaServeResponse"
OpaServeResponseWithReqBodyName = "opaServeResponseWithReqBody"
TLSName = "tlsPassClientCertificates"
WASMName = "wasm"

// Undocumented filters
HealthCheckName = "healthcheck"
Expand Down
15 changes: 15 additions & 0 deletions filters/wasm/testdata/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

//export request
func request(x, y uint32) uint32 {
return x + y
}

//export response
func response(x, y uint32) uint32 {
return x - y
}

// main is required for the `wasi` target, even if it isn't used.
// See https://wazero.io/languages/tinygo/#why-do-i-have-to-define-main
func main() {}
Binary file added filters/wasm/testdata/add.wasm
Binary file not shown.
104 changes: 104 additions & 0 deletions filters/wasm/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package wasm

import (
"context"
"net/url"
"os"

"github.com/sirupsen/logrus"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/zalando/skipper/filters"
)

type wasmSpec struct{}

type wasm struct {
code []byte
mod api.Module
request api.Function
response api.Function
}

func NewWASM() filters.Spec {
return &wasmSpec{}
}

// Name implements filters.Spec.
func (*wasmSpec) Name() string {
return filters.WASMName
}

// CreateFilter implements filters.Spec.
func (*wasmSpec) CreateFilter(args []interface{}) (filters.Filter, error) {
if len(args) != 1 {
return nil, filters.ErrInvalidFilterParameters
}
src, ok := args[0].(string)
if !ok {
return nil, filters.ErrInvalidFilterParameters
}
u, err := url.Parse(src)
if err != nil {
return nil, filters.ErrInvalidFilterParameters
}

var code []byte

switch u.Scheme {
case "file":
code, err = os.ReadFile(u.Path)
Copy link
Member

Choose a reason for hiding this comment

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

I think we should make this lazy and cacheable and cleanup on filter close

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, as I wrote in the PR title super basic. I used https://github.com/tetratelabs/wazero/tree/main/examples/basic to test the super basic example.

if err != nil {
logrus.Errorf("Failed to load file %q: %v", u.Path, err)
return nil, filters.ErrInvalidFilterParameters
}
case "https":
panic("not implemented")
default:
return nil, filters.ErrInvalidFilterParameters
}

ctx := context.Background()
r := wazero.NewRuntime(ctx) // TODO: needs r.Close()
// Instantiate WASI, which implements host functions needed for TinyGo to
// implement `panic`.
wasi_snapshot_preview1.MustInstantiate(ctx, r)

// Instantiate the guest Wasm into the same runtime. It exports the `add`
// function, implemented in WebAssembly.
mod, err := r.Instantiate(ctx, code)
if err != nil {
logrus.Fatalf("failed to instantiate module: %v", err)
}
request := mod.ExportedFunction("request")
response := mod.ExportedFunction("response")

return &wasm{
code: code,
mod: mod,
request: request,
response: response,
}, nil
}

// Request implements filters.Filter.
func (w *wasm) Request(filters.FilterContext) {

result, err := w.request.Call(context.Background(), 2, 3)
if err != nil {
logrus.Errorf("failed to call add: %v", err)
}
logrus.Infof("request result: %v", result)

}

// Response implements filters.Filter.
func (w *wasm) Response(filters.FilterContext) {
result, err := w.response.Call(context.Background(), 3, 2)
if err != nil {
logrus.Errorf("failed to call add: %v", err)
}
logrus.Infof("response result: %v", result)

}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ require (
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/tetratelabs/wazero v1.6.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BG
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/testcontainers/testcontainers-go v0.27.0 h1:IeIrJN4twonTDuMuBNQdKZ+K97yd7VrmNGu+lDpYcDk=
github.com/testcontainers/testcontainers-go v0.27.0/go.mod h1:+HgYZcd17GshBUZv9b+jKFJ198heWPQq3KQIp2+N+7U=
github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g=
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
Expand Down
Loading