Skip to content
This repository was archived by the owner on Apr 24, 2025. It is now read-only.

Commit 0894850

Browse files
feat: add GetRootContextByID call (#93)
* feat: add GetRootContextByID call * test: add example+test for getting config from root context
1 parent c4a44c4 commit 0894850

File tree

5 files changed

+236
-0
lines changed

5 files changed

+236
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## configuration_from_root
2+
3+
This example reads the json string from Envoy's configuration yaml at the startup time
4+
The child HTTP context then reads the config from its corresponding root context.
5+
6+
```
7+
wasm log my_root_id: plugin config: {
8+
"name": "plugin configuration"
9+
}
10+
```
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
static_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+
config:
12+
stat_prefix: ingress_http
13+
codec_type: auto
14+
route_config:
15+
name: local_route
16+
virtual_hosts:
17+
- name: local_service
18+
domains:
19+
- "*"
20+
routes:
21+
- match:
22+
prefix: "/"
23+
route:
24+
cluster: web_service
25+
http_filters:
26+
- name: envoy.filters.http.wasm
27+
typed_config:
28+
"@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
29+
config:
30+
configuration:
31+
"@type": type.googleapis.com/google.protobuf.StringValue
32+
value: |
33+
{
34+
"name": "plugin configuration"
35+
}
36+
name: "my_plugin"
37+
root_id: "my_root_id"
38+
vm_config:
39+
vm_id: "my_vm_id"
40+
runtime: envoy.wasm.runtime.v8
41+
code:
42+
local:
43+
filename: "./examples/configuration_from_root/main.go.wasm"
44+
allow_precompiled: true
45+
- name: envoy.filters.http.router
46+
47+
- name: staticreply
48+
address:
49+
socket_address:
50+
address: 127.0.0.1
51+
port_value: 8099
52+
filter_chains:
53+
- filters:
54+
- name: envoy.http_connection_manager
55+
config:
56+
stat_prefix: ingress_http
57+
codec_type: auto
58+
route_config:
59+
name: local_route
60+
virtual_hosts:
61+
- name: local_service
62+
domains:
63+
- "*"
64+
routes:
65+
- match:
66+
prefix: "/"
67+
direct_response:
68+
status: 200
69+
body:
70+
inline_string: "example body\n"
71+
http_filters:
72+
- name: envoy.router
73+
config: {}
74+
75+
clusters:
76+
- name: web_service
77+
connect_timeout: 0.25s
78+
type: static
79+
lb_policy: round_robin
80+
hosts:
81+
- socket_address:
82+
address: 127.0.0.1
83+
port_value: 8099
84+
admin:
85+
access_log_path: "/dev/null"
86+
address:
87+
socket_address:
88+
address: 0.0.0.0
89+
port_value: 8001
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright 2020 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+
15+
package main
16+
17+
import (
18+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
19+
)
20+
21+
func main() {
22+
proxywasm.SetNewRootContext(newRootContext)
23+
proxywasm.SetNewHttpContext(newHttpContext)
24+
}
25+
26+
type rootContext struct {
27+
// you must embed the default context so that you need not to reimplement all the methods by yourself
28+
proxywasm.DefaultRootContext
29+
30+
config []byte
31+
}
32+
33+
func newRootContext(contextID uint32) proxywasm.RootContext {
34+
return &rootContext{}
35+
}
36+
37+
func (ctx *rootContext) OnPluginStart(pluginConfigurationSize int) bool {
38+
data, err := proxywasm.GetPluginConfiguration(pluginConfigurationSize)
39+
if err != nil {
40+
proxywasm.LogCriticalf("error reading plugin configuration: %v", err)
41+
}
42+
43+
ctx.config = data
44+
return true
45+
}
46+
47+
type httpContext struct {
48+
proxywasm.DefaultHttpContext
49+
50+
config []byte
51+
}
52+
53+
func newHttpContext(rootContextID, contextID uint32) proxywasm.HttpContext {
54+
ctx := &httpContext{}
55+
56+
rootCtx, err := proxywasm.GetRootContextByID(rootContextID)
57+
if err != nil {
58+
proxywasm.LogErrorf("unable to get root context: %v", err)
59+
60+
return ctx
61+
}
62+
63+
exampleRootCtx, ok := rootCtx.(*rootContext)
64+
if !ok {
65+
proxywasm.LogError("could not cast root context")
66+
}
67+
68+
ctx.config = exampleRootCtx.config
69+
70+
proxywasm.LogInfof("plugin config: %s\n", string(ctx.config))
71+
return ctx
72+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2020 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+
15+
package main
16+
17+
import (
18+
"strings"
19+
"testing"
20+
21+
"github.com/stretchr/testify/require"
22+
23+
"github.com/stretchr/testify/assert"
24+
25+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxytest"
26+
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
27+
)
28+
29+
func TestContext_OnPluginStart(t *testing.T) {
30+
pluginConfigData := `{"name": "tinygo plugin configuration"}`
31+
32+
opt := proxytest.NewEmulatorOption().
33+
WithNewRootContext(newRootContext).
34+
WithNewHttpContext(newHttpContext).
35+
WithPluginConfiguration([]byte(pluginConfigData))
36+
host := proxytest.NewHostEmulator(opt)
37+
defer host.Done() // release the emulation lock so that other test cases can insert their own host emulation
38+
39+
host.StartPlugin() // invoke OnPluginStart
40+
41+
host.HttpFilterInitContext()
42+
43+
errLogs := host.GetLogs(types.LogLevelError)
44+
require.Len(t, errLogs, 0)
45+
46+
logs := host.GetLogs(types.LogLevelInfo)
47+
require.Greater(t, len(logs), 0)
48+
msg := logs[len(logs)-1]
49+
assert.True(t, strings.Contains(msg, pluginConfigData))
50+
}

proxywasm/vmstate.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
package proxywasm
1616

17+
import (
18+
"errors"
19+
"fmt"
20+
)
21+
1722
type (
1823
HttpCalloutCallBack = func(numHeaders, bodySize, numTrailers int)
1924

@@ -57,6 +62,16 @@ func SetNewStreamContext(f func(rootContextID, contextID uint32) StreamContext)
5762
currentState.newStreamContext = f
5863
}
5964

65+
var ErrorRootContextNotFound = errors.New("root context not found")
66+
67+
func GetRootContextByID(rootContextID uint32) (RootContext, error) {
68+
rootContextState, ok := currentState.rootContexts[rootContextID]
69+
if !ok {
70+
return nil, fmt.Errorf("%w: %d", ErrorRootContextNotFound, rootContextID)
71+
}
72+
return rootContextState.context, nil
73+
}
74+
6075
//go:inline
6176
func (s *state) createRootContext(contextID uint32) {
6277
var ctx RootContext

0 commit comments

Comments
 (0)