Envoyproxy write wasm plugin getting started

The Dockerfile from envoyproxy base image inherit

1FROM envoyproxy/envoy:v1.27-latest
2
3COPY envoy.yaml /etc/envoy/envoy.yaml
4COPY hello.wasm hello.wasm
5RUN chmod go+r /etc/envoy/envoy.yaml

The EnvoyProxy config envoy.yaml

 1static_resources:
 2  listeners:
 3    - name: main
 4      address:
 5        socket_address:
 6          address: 0.0.0.0
 7          port_value: 18000
 8      filter_chains:
 9        - filters:
10            - name: envoy.http_connection_manager
11              typed_config:
12                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
13                stat_prefix: ingress_http
14                codec_type: auto
15                route_config:
16                  name: local_route
17                  virtual_hosts:
18                    - name: local_service
19                      domains:
20                        - "*"
21                      routes:
22                        - match:
23                            prefix: "/"
24                          direct_response:
25                            status: 200
26                            body:
27                              inline_string: "example body\n"
28                http_filters:
29                  - name: envoy.filters.http.wasm
30                    typed_config:
31                      "@type": type.googleapis.com/udpa.type.v1.TypedStruct
32                      type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
33                      value:
34                        config:
35                          vm_config:
36                            runtime: "envoy.wasm.runtime.v8"
37                            code:
38                              local:
39                                filename: "./hello.wasm"
40                  - name: envoy.filters.http.router
41                    typed_config:
42                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
43
44admin:
45  access_log_path: "/dev/null"
46  address:
47    socket_address:
48      address: 0.0.0.0
49      port_value: 8001

The main.goto construction the wasm plugin

 1// Copyright 2020-2021 Tetrate
 2//
 3// Licensed under the Apache License, Version 2.0 (the "License");
 4// you may not use this file except in compliance with the License.
 5// You may obtain a copy of the License at
 6//
 7// http://www.apache.org/licenses/LICENSE-2.0
 8//
 9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18	"math/rand"
19	"time"
20
21	"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
22	"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
23)
24
25const tickMilliseconds uint32 = 1000
26
27func main() {
28	proxywasm.SetVMContext(&vmContext{})
29}
30
31type vmContext struct {
32	// Embed the default VM context here,
33	// so that we don't need to reimplement all the methods.
34	types.DefaultVMContext
35}
36
37// Override types.DefaultVMContext.
38func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
39	return &helloWorld{}
40}
41
42type helloWorld struct {
43	// Embed the default plugin context here,
44	// so that we don't need to reimplement all the methods.
45	types.DefaultPluginContext
46	contextID uint32
47}
48
49// Override types.DefaultPluginContext.
50func (ctx *helloWorld) OnPluginStart(pluginConfigurationSize int) types.OnPluginStartStatus {
51	rand.Seed(time.Now().UnixNano())
52
53	proxywasm.LogInfo("OnPluginStart from Go!")
54	if err := proxywasm.SetTickPeriodMilliSeconds(tickMilliseconds); err != nil {
55		proxywasm.LogCriticalf("failed to set tick period: %v", err)
56	}
57
58	return types.OnPluginStartStatusOK
59}
60
61// Override types.DefaultPluginContext.
62func (ctx *helloWorld) OnTick() {
63	t := time.Now().UnixNano()
64	proxywasm.LogInfof("It's %d: random value: %d", t, rand.Uint64())
65	proxywasm.LogInfof("OnTick called")
66}
67
68// Override types.DefaultPluginContext.
69func (*helloWorld) NewHttpContext(uint32) types.HttpContext { return &types.DefaultHttpContext{} }

install TinyGo

1brew tap tinygo-org/tools
2brew install tinygo

The Makefile to build and make the wasm and image

1wasm_name := hello.wasm
2image_tag := hello-v1
3
4build.wasm:
5	tinygo build -o $(wasm_name) -scheduler=none -target=wasi main.go
6build.image: build.wasm
7	docker buildx build --platform=linux/amd64 -t envoyproxy/envoy:$(image_tag) . -f ./Dockerfile

Dynamic change envoyproxy loggin level

1$ kubectl -n default exec "$(kubectl get pod -l app=helloworld -o jsonpath='{.items[0].metadata.name}')" -c istio-proxy pilot-agent request POST /logging"?wasm=info"

Happy to wasm debug