You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2021/10/27 02:27:35 UTC
[apisix] branch master updated: test(wasm): add fault-injection
example (#5337)
This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 9df6e88 test(wasm): add fault-injection example (#5337)
9df6e88 is described below
commit 9df6e887349e31e9159f99dc7a874dba3798a299
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Wed Oct 27 10:27:27 2021 +0800
test(wasm): add fault-injection example (#5337)
---
t/wasm/fault-injection.t | 186 +++++++++++++++++++++++++++++++++++++++++
t/wasm/fault-injection/main.go | 108 ++++++++++++++++++++++++
t/wasm/go.mod | 6 +-
t/wasm/go.sum | 7 ++
4 files changed, 306 insertions(+), 1 deletion(-)
diff --git a/t/wasm/fault-injection.t b/t/wasm/fault-injection.t
new file mode 100644
index 0000000..addeddd
--- /dev/null
+++ b/t/wasm/fault-injection.t
@@ -0,0 +1,186 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX;
+
+my $nginx_binary = $ENV{'TEST_NGINX_BINARY'} || 'nginx';
+my $version = eval { `$nginx_binary -V 2>&1` };
+
+if ($version !~ m/\/apisix-nginx-module/) {
+ plan(skip_all => "apisix-nginx-module not installed");
+} else {
+ plan('no_plan');
+}
+
+add_block_preprocessor(sub {
+ my ($block) = @_;
+
+ if ((!defined $block->error_log) && (!defined $block->no_error_log)) {
+ $block->set_value("no_error_log", "[error]");
+ }
+
+ if (!defined $block->request) {
+ $block->set_value("request", "GET /t");
+ }
+
+ my $extra_yaml_config = <<_EOC_;
+wasm:
+ plugins:
+ - name: wasm_fault_injection
+ priority: 7997
+ file: t/wasm/fault-injection/main.go.wasm
+_EOC_
+ $block->set_value("extra_yaml_config", $extra_yaml_config);
+});
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: fault injection
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:1980": 1
+ }
+ },
+ "plugins": {
+ "wasm_fault_injection": {
+ "conf": "{\"http_status\":401, \"body\":\"HIT\n\"}"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 2: hit
+--- request
+GET /hello
+--- error_code: 401
+--- response_body
+HIT
+
+
+
+=== TEST 3: fault injection, with 0 percentage
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:1980": 1
+ }
+ },
+ "plugins": {
+ "wasm_fault_injection": {
+ "conf": "{\"http_status\":401, \"percentage\":0}"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 4: hit
+--- request
+GET /hello
+--- response_body
+hello world
+
+
+
+=== TEST 5: fault injection without body
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "uri": "/hello",
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:1980": 1
+ }
+ },
+ "plugins": {
+ "wasm_fault_injection": {
+ "conf": "{\"http_status\":401}"
+ }
+ }
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ ngx.say(body)
+ return
+ end
+
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 6: hit
+--- request
+GET /hello
+--- error_code: 401
+--- response_body_like eval
+qr/<title>401 Authorization Required<\/title>/
diff --git a/t/wasm/fault-injection/main.go b/t/wasm/fault-injection/main.go
new file mode 100644
index 0000000..698bb97
--- /dev/null
+++ b/t/wasm/fault-injection/main.go
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+ "math/rand"
+
+ "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
+ "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
+
+ // tinygo doesn't support encoding/json, see https://github.com/tinygo-org/tinygo/issues/447
+ "github.com/valyala/fastjson"
+)
+
+func main() {
+ proxywasm.SetVMContext(&vmContext{})
+}
+
+type vmContext struct {
+ types.DefaultVMContext
+}
+
+func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
+ return &pluginContext{}
+}
+
+type pluginContext struct {
+ types.DefaultPluginContext
+ Body []byte
+ HttpStatus uint32
+ Percentage int
+}
+
+func (ctx *pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPluginStartStatus {
+ data, err := proxywasm.GetPluginConfiguration()
+ if err != nil {
+ proxywasm.LogErrorf("error reading plugin configuration: %v", err)
+ return types.OnPluginStartStatusFailed
+ }
+
+ var p fastjson.Parser
+ v, err := p.ParseBytes(data)
+ if err != nil {
+ proxywasm.LogErrorf("erorr decoding plugin configuration: %v", err)
+ return types.OnPluginStartStatusFailed
+ }
+ ctx.Body = v.GetStringBytes("body")
+ ctx.HttpStatus = uint32(v.GetUint("http_status"))
+ if v.Exists("percentage") {
+ ctx.Percentage = v.GetInt("percentage")
+ } else {
+ ctx.Percentage = 100
+ }
+
+ // schema check
+ if ctx.HttpStatus < 200 {
+ proxywasm.LogError("bad http_status")
+ return types.OnPluginStartStatusFailed
+ }
+ if ctx.Percentage < 0 || ctx.Percentage > 100 {
+ proxywasm.LogError("bad percentage")
+ return types.OnPluginStartStatusFailed
+ }
+
+ return types.OnPluginStartStatusOK
+}
+
+func (ctx *pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
+ return &httpLifecycle{parent: ctx}
+}
+
+type httpLifecycle struct {
+ types.DefaultHttpContext
+ parent *pluginContext
+}
+
+func sampleHit(percentage int) bool {
+ return rand.Intn(100) < percentage
+}
+
+func (ctx *httpLifecycle) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
+ plugin := ctx.parent
+ if !sampleHit(plugin.Percentage) {
+ return types.ActionContinue
+ }
+
+ err := proxywasm.SendHttpResponse(plugin.HttpStatus, nil, plugin.Body, -1)
+ if err != nil {
+ proxywasm.LogErrorf("failed to send local response: %v", err)
+ return types.ActionContinue
+ }
+ return types.ActionPause
+}
diff --git a/t/wasm/go.mod b/t/wasm/go.mod
index 9a875c8..3f9de8a 100644
--- a/t/wasm/go.mod
+++ b/t/wasm/go.mod
@@ -2,5 +2,9 @@ module github.com/api7/wasm-nginx-module
go 1.15
-require github.com/tetratelabs/proxy-wasm-go-sdk v0.14.1-0.20210819090022-1e4e69881a31
+require (
+ github.com/tetratelabs/proxy-wasm-go-sdk v0.14.1-0.20210819090022-1e4e69881a31
+ github.com/valyala/fastjson v1.6.3
+)
+
//replace github.com/tetratelabs/proxy-wasm-go-sdk => ../proxy-wasm-go-sdk
diff --git a/t/wasm/go.sum b/t/wasm/go.sum
index 599f226..97ddff7 100644
--- a/t/wasm/go.sum
+++ b/t/wasm/go.sum
@@ -1,8 +1,15 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tetratelabs/proxy-wasm-go-sdk v0.14.1-0.20210819090022-1e4e69881a31 h1:V3GXN5nayOdIU3NypbxVegGFCVGm78qOA8Q7wkeudy8=
github.com/tetratelabs/proxy-wasm-go-sdk v0.14.1-0.20210819090022-1e4e69881a31/go.mod h1:qZ+4i6e2wHlhnhgpH0VG4QFzqd2BEvQbQFU0npt2e2k=
+github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc=
+github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=