Skip to content

Commit d1f3a8f

Browse files
author
xuleiming
committed
bfe_wasm
Signed-off-by: xuleiming <[email protected]>
1 parent 9f0a6be commit d1f3a8f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2562
-51
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ strip: prepare compile-strip package
7474
# make prepare, download dependencies
7575
prepare: prepare-dep prepare-gen
7676
prepare-dep:
77-
$(call INSTALL_PKG, goyacc, golang.org/x/tools/cmd/goyacc)
77+
$(call INSTALL_PKG, goyacc, golang.org/x/tools/cmd/goyacc@latest)
7878
prepare-gen:
7979
cd "bfe_basic/condition/parser" && $(GOGEN)
8080

@@ -117,7 +117,7 @@ package:
117117
# make deps
118118
deps:
119119
$(call PIP_INSTALL_PKG, pre-commit)
120-
$(call INSTALL_PKG, goyacc, golang.org/x/tools/cmd/goyacc)
120+
$(call INSTALL_PKG, goyacc, golang.org/x/tools/cmd/goyacc@latest)
121121
$(call INSTALL_PKG, staticcheck, honnef.co/go/tools/cmd/staticcheck)
122122
$(call INSTALL_PKG, license-eye, github.com/apache/skywalking-eyes/cmd/license-eye@latest)
123123

bfe_config/bfe_conf/conf_basic.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ type ConfigBasic struct {
7272
DebugBfeRoute bool // whether open bferoute debug log
7373
DebugBal bool // whether open bal debug log
7474
DebugHealthCheck bool // whether open health check debug log
75+
76+
// wasm plugin path
77+
BfeWasmPath string //root path of wasm plugins
7578
}
7679

7780
func (cfg *ConfigBasic) SetDefaultConf() {
@@ -99,6 +102,8 @@ func (cfg *ConfigBasic) SetDefaultConf() {
99102
cfg.NameConf = "server_data_conf/name_conf.data"
100103

101104
cfg.MonitorInterval = 20
105+
106+
cfg.BfeWasmPath = "plugin"
102107
}
103108

104109
func (cfg *ConfigBasic) Check(confRoot string) error {

bfe_modules/bfe_modules.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"github.com/bfenetworks/bfe/bfe_modules/mod_trust_clientip"
4545
"github.com/bfenetworks/bfe/bfe_modules/mod_userid"
4646
"github.com/bfenetworks/bfe/bfe_modules/mod_waf"
47+
"github.com/bfenetworks/bfe/bfe_modules/mod_wasmplug"
4748
)
4849

4950
// list of all modules, the order is very important
@@ -131,6 +132,9 @@ var moduleList = []bfe_module.BfeModule{
131132

132133
// mod_access
133134
mod_access.NewModuleAccess(),
135+
136+
// mod_wasm
137+
mod_wasmplug.NewModuleWasm(),
134138
}
135139

136140
// init modules list
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
package mod_wasmplug
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path"
7+
"sync"
8+
9+
"github.com/baidu/go-lib/log"
10+
"github.com/bfenetworks/bfe/bfe_basic/condition"
11+
"github.com/bfenetworks/bfe/bfe_util"
12+
"github.com/bfenetworks/bfe/bfe_util/json"
13+
"github.com/bfenetworks/bfe/bfe_wasmplug"
14+
gcfg "gopkg.in/gcfg.v1"
15+
)
16+
17+
type ConfModWasm struct {
18+
Basic struct {
19+
WasmPluginPath string // path of Wasm plugins
20+
DataPath string // path of config data
21+
}
22+
23+
Log struct {
24+
OpenDebug bool
25+
}
26+
}
27+
28+
// ConfLoad loads config from config file
29+
func ConfLoad(filePath string, confRoot string) (*ConfModWasm, error) {
30+
var cfg ConfModWasm
31+
var err error
32+
33+
// read config from file
34+
err = gcfg.ReadFileInto(&cfg, filePath)
35+
if err != nil {
36+
return &cfg, err
37+
}
38+
39+
// check conf of mod_redirect
40+
err = cfg.Check(confRoot)
41+
if err != nil {
42+
return &cfg, err
43+
}
44+
45+
return &cfg, nil
46+
}
47+
48+
func (cfg *ConfModWasm) Check(confRoot string) error {
49+
if cfg.Basic.WasmPluginPath == "" {
50+
log.Logger.Warn("ModWasm.WasmPluginPath not set, use default value")
51+
cfg.Basic.WasmPluginPath = "mod_wasm"
52+
}
53+
cfg.Basic.WasmPluginPath = bfe_util.ConfPathProc(cfg.Basic.WasmPluginPath, confRoot)
54+
55+
if cfg.Basic.DataPath == "" {
56+
log.Logger.Warn("ModWasm.DataPath not set, use default value")
57+
cfg.Basic.WasmPluginPath = "mod_wasm/wasm.data"
58+
}
59+
cfg.Basic.DataPath = bfe_util.ConfPathProc(cfg.Basic.DataPath, confRoot)
60+
61+
return nil
62+
}
63+
64+
type PluginConfFile struct {
65+
Version *string // version of the config
66+
BeforeLocationRules *[]FilterRuleFile // rule list for BeforeLocation
67+
ProductRules *map[string][]FilterRuleFile // product --> rule list
68+
PluginMap *map[string]PluginMeta
69+
}
70+
71+
type FilterRuleFile struct {
72+
Cond *string // condition for plugin
73+
PluginList *[]string
74+
}
75+
76+
type PluginMeta struct {
77+
Name string
78+
WasmVersion string
79+
ConfVersion string
80+
// Md5 string
81+
InstanceNum int
82+
Product string
83+
}
84+
85+
type FilterRule struct {
86+
Cond condition.Condition // condition for plugin
87+
PluginList []*bfe_wasmplug.WasmPlugin
88+
}
89+
90+
type RuleList []FilterRule
91+
type ProductRules map[string]*RuleList // product => list of filter rules
92+
93+
func updatePluginConf(t *PluginTable, conf PluginConfFile, pluginPath string) error {
94+
if conf.Version != nil && *conf.Version != t.GetVersion() {
95+
pluginMapNew := make(map[string]*bfe_wasmplug.WasmPlugin)
96+
var beforeLocationRulesNew RuleList
97+
productRulesNew := make(ProductRules)
98+
99+
// 1. check plugin map
100+
unchanged := make(map[string]bool)
101+
102+
pm := t.GetPluginMap()
103+
if conf.PluginMap != nil {
104+
for pn, p := range *conf.PluginMap {
105+
plugOld := (*pm)[pn]
106+
// check whether plugin version changed.
107+
if plugOld != nil {
108+
configOld := (*plugOld).GetConfig()
109+
if configOld.WasmVersion == p.WasmVersion && configOld.ConfigVersion == p.ConfVersion {
110+
// not change, just copy to new map
111+
pluginMapNew[pn] = plugOld
112+
113+
// ensure instance num
114+
actual := (*plugOld).EnsureInstanceNum(p.InstanceNum)
115+
if actual != p.InstanceNum {
116+
// log.DefaultLogger.Errorf("[wasm][plugin] NewWasmPlugin fail to ensure instance num, want: %v got 0", instanceNum)
117+
return fmt.Errorf("can not EnsureInstanceNum, plugin:%s, num:%d", pn, p.InstanceNum)
118+
}
119+
120+
unchanged[pn] = true
121+
continue
122+
}
123+
}
124+
// if changed, construct a new plugin.
125+
wasmconf := bfe_wasmplug.WasmPluginConfig {
126+
PluginName: pn,
127+
WasmVersion: p.WasmVersion,
128+
ConfigVersion: p.ConfVersion,
129+
InstanceNum: p.InstanceNum,
130+
Path: path.Join(pluginPath, pn),
131+
// Md5: p.Md5,
132+
}
133+
plug, err := bfe_wasmplug.NewWasmPlugin(wasmconf)
134+
if err != nil {
135+
// build plugin error
136+
return err
137+
}
138+
139+
plug.OnPluginStart()
140+
141+
pluginMapNew[pn] = &plug
142+
}
143+
}
144+
145+
// 2. construct product rules
146+
if conf.BeforeLocationRules != nil {
147+
for _, r := range *conf.BeforeLocationRules {
148+
rule := FilterRule{}
149+
cond, err := condition.Build(*r.Cond)
150+
if err != nil {
151+
return err
152+
}
153+
rule.Cond =cond
154+
for _, pn := range *r.PluginList {
155+
plug := pluginMapNew[pn]
156+
if plug == nil {
157+
return fmt.Errorf("unknown plugin: %s", pn)
158+
}
159+
rule.PluginList = append(rule.PluginList, plug)
160+
}
161+
beforeLocationRulesNew = append(beforeLocationRulesNew, rule)
162+
}
163+
}
164+
165+
if conf.ProductRules != nil {
166+
for product, rules := range *conf.ProductRules {
167+
var rulelist RuleList
168+
for _, r := range rules {
169+
rule := FilterRule{}
170+
cond, err := condition.Build(*r.Cond)
171+
if err != nil {
172+
return err
173+
}
174+
rule.Cond =cond
175+
for _, pn := range *r.PluginList {
176+
plug := pluginMapNew[pn]
177+
if plug == nil {
178+
return fmt.Errorf("unknown plugin: %s", pn)
179+
}
180+
rule.PluginList = append(rule.PluginList, plug)
181+
}
182+
rulelist = append(rulelist, rule)
183+
}
184+
productRulesNew[product] = &rulelist
185+
}
186+
}
187+
188+
// 3. update PluginTable
189+
t.Update(*conf.Version, &beforeLocationRulesNew, productRulesNew, &pluginMapNew)
190+
191+
// 4. stop & clear old plugins
192+
for pn, plug := range *pm {
193+
if _, ok := unchanged[pn]; !ok {
194+
// stop plug
195+
(*plug).OnPluginDestroy()
196+
(*plug).Clear()
197+
}
198+
}
199+
}
200+
return nil
201+
}
202+
203+
type PluginTable struct {
204+
lock sync.RWMutex
205+
version string
206+
beforeLocationRules *RuleList
207+
productRules ProductRules
208+
pluginMap *map[string]*bfe_wasmplug.WasmPlugin
209+
}
210+
211+
func NewPluginTable() *PluginTable {
212+
t := new(PluginTable)
213+
t.productRules = make(ProductRules)
214+
t.pluginMap = new(map[string]*bfe_wasmplug.WasmPlugin)
215+
return t
216+
}
217+
218+
func (t *PluginTable) Update(version string, beforeLocationRules *RuleList, productRules ProductRules, pluginMap *map[string]*bfe_wasmplug.WasmPlugin) {
219+
t.lock.Lock()
220+
221+
t.version = version
222+
t.beforeLocationRules = beforeLocationRules
223+
t.productRules = productRules
224+
t.pluginMap = pluginMap
225+
226+
t.lock.Unlock()
227+
}
228+
229+
func (t *PluginTable) GetVersion() string {
230+
defer t.lock.RUnlock()
231+
t.lock.RLock()
232+
return t.version
233+
}
234+
235+
func (t *PluginTable) GetPluginMap() *map[string]*bfe_wasmplug.WasmPlugin {
236+
defer t.lock.RUnlock()
237+
t.lock.RLock()
238+
return t.pluginMap
239+
}
240+
241+
func (t *PluginTable) GetBeforeLocationRules() *RuleList {
242+
defer t.lock.RUnlock()
243+
t.lock.RLock()
244+
return t.beforeLocationRules
245+
}
246+
247+
func (t *PluginTable) Search(product string) (*RuleList, bool) {
248+
t.lock.RLock()
249+
productRules := t.productRules
250+
t.lock.RUnlock()
251+
252+
rules, ok := productRules[product]
253+
return rules, ok
254+
}
255+
256+
257+
func pluginConfLoad(filename string) (PluginConfFile, error) {
258+
var conf PluginConfFile
259+
260+
/* open the file */
261+
file, err := os.Open(filename)
262+
263+
if err != nil {
264+
return conf, err
265+
}
266+
267+
/* decode the file */
268+
decoder := json.NewDecoder(file)
269+
270+
err = decoder.Decode(&conf)
271+
file.Close()
272+
273+
if err != nil {
274+
return conf, err
275+
}
276+
277+
return conf, nil
278+
}

0 commit comments

Comments
 (0)