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/11/02 02:08:40 UTC

[apisix-go-plugin-runner] branch master updated: feat: add fault-injection plugin for benchmark (#46)

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-go-plugin-runner.git


The following commit(s) were added to refs/heads/master by this push:
     new 195bd64  feat: add fault-injection plugin for benchmark (#46)
195bd64 is described below

commit 195bd64e4d0edeb471a43016f0c3f0dad59f86b9
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Tue Nov 2 10:08:36 2021 +0800

    feat: add fault-injection plugin for benchmark (#46)
---
 cmd/go-runner/plugins/fault_injection.go      | 96 +++++++++++++++++++++++++++
 cmd/go-runner/plugins/fault_injection_test.go | 52 +++++++++++++++
 2 files changed, 148 insertions(+)

diff --git a/cmd/go-runner/plugins/fault_injection.go b/cmd/go-runner/plugins/fault_injection.go
new file mode 100644
index 0000000..9f04299
--- /dev/null
+++ b/cmd/go-runner/plugins/fault_injection.go
@@ -0,0 +1,96 @@
+/*
+ * 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 plugins
+
+import (
+	"encoding/json"
+	"errors"
+	"math/rand"
+	"net/http"
+
+	pkgHTTP "github.com/apache/apisix-go-plugin-runner/pkg/http"
+	"github.com/apache/apisix-go-plugin-runner/pkg/log"
+	"github.com/apache/apisix-go-plugin-runner/pkg/plugin"
+)
+
+const (
+	plugin_name = "fault-injection"
+)
+
+func init() {
+	err := plugin.RegisterPlugin(&FaultInjection{})
+	if err != nil {
+		log.Fatalf("failed to register plugin %s: %s", plugin_name, err)
+	}
+}
+
+// FaultInjection is used in the benchmark
+type FaultInjection struct {
+}
+
+type FaultInjectionConf struct {
+	Body       string `json:"body"`
+	HttpStatus int    `json:"http_status"`
+	Percentage int    `json:"percentage"`
+}
+
+func (p *FaultInjection) Name() string {
+	return plugin_name
+}
+
+func (p *FaultInjection) ParseConf(in []byte) (interface{}, error) {
+	conf := FaultInjectionConf{Percentage: -1}
+	err := json.Unmarshal(in, &conf)
+	if err != nil {
+		return nil, err
+	}
+
+	// schema check
+	if conf.HttpStatus < 200 {
+		return nil, errors.New("bad http_status")
+	}
+	if conf.Percentage == -1 {
+		conf.Percentage = 100
+	} else if conf.Percentage < 0 || conf.Percentage > 100 {
+		return nil, errors.New("bad percentage")
+	}
+
+	return conf, err
+}
+
+func sampleHit(percentage int) bool {
+	return rand.Intn(100) < percentage
+}
+
+func (p *FaultInjection) Filter(conf interface{}, w http.ResponseWriter, r pkgHTTP.Request) {
+	fc := conf.(FaultInjectionConf)
+	if !sampleHit(fc.Percentage) {
+		return
+	}
+
+	w.WriteHeader(fc.HttpStatus)
+	body := fc.Body
+	if len(body) == 0 {
+		return
+	}
+
+	_, err := w.Write([]byte(body))
+	if err != nil {
+		log.Errorf("failed to write: %s", err)
+	}
+}
diff --git a/cmd/go-runner/plugins/fault_injection_test.go b/cmd/go-runner/plugins/fault_injection_test.go
new file mode 100644
index 0000000..eb073f9
--- /dev/null
+++ b/cmd/go-runner/plugins/fault_injection_test.go
@@ -0,0 +1,52 @@
+/*
+ * 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 plugins
+
+import (
+	"io/ioutil"
+	"net/http/httptest"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestFaultInjection(t *testing.T) {
+	in := []byte(`{"http_status":400, "body":"hello"}`)
+	fi := &FaultInjection{}
+	conf, err := fi.ParseConf(in)
+	assert.Nil(t, err)
+
+	w := httptest.NewRecorder()
+	fi.Filter(conf, w, nil)
+	resp := w.Result()
+	body, _ := ioutil.ReadAll(resp.Body)
+	assert.Equal(t, 400, resp.StatusCode)
+	assert.Equal(t, "hello", string(body))
+}
+
+func TestFaultInjection_Percentage(t *testing.T) {
+	in := []byte(`{"http_status":400, "percentage":0}`)
+	fi := &FaultInjection{}
+	conf, err := fi.ParseConf(in)
+	assert.Nil(t, err)
+
+	w := httptest.NewRecorder()
+	fi.Filter(conf, w, nil)
+	resp := w.Result()
+	assert.Equal(t, 200, resp.StatusCode)
+}